/**
 * Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef LIBBITCOIN_SYSTEM_TEST_HASH_HASH_HPP
#define LIBBITCOIN_SYSTEM_TEST_HASH_HASH_HPP

#include "../test.hpp"

// null hash vectors.
constexpr auto rmd_half128 = base16_array("c11f675df95fe3f7f00b6825368bce48");
constexpr auto rmd_full128 = base16_array("082bfa9b829ef3a9e220dcc54e4c6383");
constexpr auto rmd_half160 = base16_array("d1a70126ff7a149ca6f9b638db084480440ff842");
constexpr auto rmd_full160 = base16_array("9b8ccc2f374ae313a914763cc9cdfb47bfe1c229");

// null hash vectors.
constexpr auto sha_byte160 = base16_array("5ba93c9db0cff93f52b521d7420e43f6eda2784f");
constexpr auto sha_half160 = base16_array("de8a847bff8c343d69b853a215e6ee775ef2ef96");
constexpr auto sha_full160 = base16_array("c8d7d0ef0eedfa82d2ea1aa592845b9a6d4b02b7");
constexpr auto sha_byte256 = base16_array("6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d");
constexpr auto sha_half256 = base16_array("66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925");
constexpr auto sha_full256 = base16_array("f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b");
constexpr auto sha_byte512 = base16_array("b8244d028981d693af7b456af8efa4cad63d282e19ff14942c246e50d9351d22704a802a71c3580b6370de4ceb293c324a8423342557d4e5c38438f0e36910ee");
constexpr auto sha_half512 = base16_array("7be9fda48f4179e611c698a73cff09faf72869431efee6eaad14de0cb44bbf66503f752b7a8eb17083355f3ce6eb7d2806f236b25af96a24e22b887405c20081");
constexpr auto sha_full512 = base16_array("ab942f526272e456ed68a979f50202905ca903a141ed98443567b11ef0bf25a552d639051a01be58558122c58e3de07d749ee59ded36acf0c55cd91924d6ba11");

#if defined (LIBBITCOIN_SYSTEM_TEST_HASH_HASH_HPP)
#define NIST_512_224C \
    "9560cb4fe668fd2180ad389206d2e57bbc9b04ea49a51375bc5532cecc0e869864a7db795f1c8d719083a86a05424e108c8059e277d942899d564269a19cb6777763c84a232a4c74c429e812d28878a2a4ceb015359c0325279bc4e908b38ca7d57edbe9bcfc02d3268840b3f50a2bda0a6f51ab0b5620f1630c03768abbced186de5c7fb2f87635be86f775f7322e60c84984cb816f5f9458924636ae1c459c936d93338b887243920c577f5f674bdbe646919d204f89b70e13d454fc3eb9b10311c72ed113bca5ad03a6fab51048f36a4dbf4a6f5f66018e78f6f6fc8af2b7deb442970b011d0214512d0d8297ee515e4558faf705bd1bdfaaf4453766b75" \
    "72c3d4a97c2b95d02d1e034e14c63059dc918a2d43eaa57ac09901668343bd139f69428567da5444eea96039d9edc557eb4ade601ceb7fd5d1511a4877b72090444a124fbc42c9a8e6a5de16afd6aa59d26ec6ba92f9275d60a17e5cc957125601c4c85af1fb62669561c1870f375bfa227bd7bf2e7a587bef089225d09a2edf7887d959917abb188b8bbeed607656934bf085c078057fdbed04ea3625f6c2b6e8f1c9ae2337403939721acc5c2a26cfbf7b5570e820f9e7db150b0042036a5703911ddb1fc77e431fc389964aa9490a1d6acb430733731a49b76916ad36a24a38f44a62ff91d1c0aeee7ffdc49a49ccb65d6bb94dd367fda96a88dbe006f70" \
    "af989d3d83b2ce72c77516245427385a23ab19b463477450c8abceed252fad513d5d05e9d7aff3b01099ad51f5caba9051b05ee6c43a596b15e1d1fac9e98c8ff5e462f35079f29c8c6395cee7bc9007fd7c8e9ae03d4d9a6a4197f9d2b574f17e379ea3189735ffe4dab4e351852487ce188f18ded8b8a36fd10935681ccd41815e9f41579122a0c007f3d85babdcd86c8b4ba8e793024fcb9b0ff5b1a5ff45a55f4f1534f02349c6f03af42fb822c180dda89223f7936627a79280d8d872c693449467d83a9fc0a19f7281f2345d0bb216901db98bd3b02afb781f033d8e8bf215587e6bfafecef71c81c5cfa5f47ea93fea92d2d72bf57da1ab1a5b5dbc5" \
    "e6bd882a314b5a73b716d5109ec9551e20e609e39956401fcc7a111b907bf6205a697fa1efbf504cfb69cc994718bdbff887f935a2bb9be8eb10194442febea494a59a83749417c526fb1d0b08710fa9dc0a6b33dbb5fcb73e3cb1b02fd6abaf2ff2774362622778b43b250a356ab16835ddce52a6edc8e7304078d3c97c33cc86f084662b91f5d43dba930b605e4977a082a11686cba7155bcbbd43a257ed693400406042bc09742de9d5831bc43e64a69961f40dc80dbe3b5f1d744d024f21a1a239c64a38d8b50f597af5ca55169bb272bf8fae6b734e394b07ea2bf3cf726a66ef0ca4a0fa235c89e1f7ee5958994ebee82deb4e6e31e0401b19b1c4e4d" \
    "7f8becea7e48cd44b8feba90e1a797ae9f5ce9a6336b95525cabea58780ce25ced72a573c7c44fdaa33ff3e8cb11e041a223234d43364de86531765b82b9818b3803a271efe61ecabc355210854bf7a866e7a45d543b940d003faaa2fe4bb24427e5eace3cd8c17ecc86def0577e644db35175c0afa2f529f77d901637eafeef83c18570f7bfc05c9adaa07088d2b09651099d5c9c94f5a410922f9d74bcecf2143e7c4167c6a4cef0da9e79626e62ed07b6241b62391ee714278f20fcec04b6a205d627d612f43b942de2f12b7b02b99e0013e34bb8f758cae3b98818a0cea3f5bd9b0c8ace380b4f7c74c22c201962df91719e9d390860fc6fb4bb1001d32" \
    "2d40fd4d7cc20f9a5e96f5ad2ad862e508f0e4633a1e6da68707288a32c369a9909a38870e430bd732aad9e0bf6d4c9ea79229a8a9fe5f4d6ef953e27b467ab715a20bfbf1a270fdcdadf48534e33729a6473768bdf5ede134180dd2eefbe8f13902f81abb62d7448c0ac5e94ffcbb2c817a9e11ea87a21882eda6da22660cde57377d71eff69761fa5bdeab54fc310da5b6de42b4460449c7e4bf76aa178ed51caa1c8003e049cca51b9f39e87441539f867869af93acfb6f87d816ea82c78be5f545d37bc266eaf8c498237ee75474db63ecf53102d4b406615169683a4f594f8399dacbef575371e159e68ce7f317e5d9ac73ed0633fa18ebebbca7909ec" \
    "3a5ef790478f9c38cacec44f196d895835b425774483043341381e7af2d383e51a59373ef1764140d165ff9d3215bc46d88484e64b6f37af882edd5af6da39699bb0a1b090ba0d13b2ac6d919b0c4082d195621c3cde253cde37a464bed354ff252ddced0da4273bd768b7323c9a3c9486af65220016f661ab1a1b9e3209fb30209691fd517cb740a6648489fd09d805619a35ff7d60d1a757a0e9123bc35783f4b467e9438ae7a889677d9cc79f3e5bc81d7bbb9d03de954a91b6c8bf4890800a4f07b8ca15ddfde7384a7580a693212502df5f474947b3ecb52cc6a7e1cdafc82f1872d067c1c628a0921c126402dcdf0f08f263783189a6d3f116dcd6369" \
    "9971b43203cc6bc8cb367fd976322b0165e0d9f7cd8d9c6a0deb5adc0456ff5c5e0dc30c8f67bf6d6f25535f05d27c8560ac34b0690b42e7ffd2109cac9f42fbb093a8675e5cd962c4c31df2fe7bd70254bfbb596725191ae6ce0ac3e52ac0f047cfdee2cf306c41629c5a65ae82ad00a897b853766f716b692ba4023c7e0ba279fed0ff7076daa1df1d72f7b4ab7128d2c0c62ee54efe51ed6766a820fd85bacdcd292dd09496dc80d302599f4ac5b369c76f4c52482276ea2ded46214dc181c9a731ee7e2e338a0e3982ebdce51d68e4181e4c3bef5042f5db826cbbd3419fe40995c1b7883312cdcd7f2eec0eda81c84f5daf00b93a3e86ecd07c6f22787" \
    "da380cf383b47080f460b41b34b2cafc68cb997d55f1a32d213fe520599bfe8a39e9948c277ef44e80d8f84e978c2ef8fb7f3676f9596cc96237c8198fa10249a1bbf9cf0dbf55c359aa6b35203662c45c09946ce52c37a034be3d996dea78ed9d1602633f5ddc060640d578d698ae8913cf7b081f504cda1e3c0d48fd5fab9db26279f1c542d1400f01febfc29b596fa93bb3f2b1aff39ea91900d046e8e2826a072420a5547c98fd54aeb1ea25ad9da5b403d1a23074145bbeded6506e64c44c6dcb99e97d243756a3acf6581ff03c8fa1354efbba1665bf916f0524d77a8ae0fd380499a41344a555c13714726b73f06c0f10c33723b95afb7b02c90d6cf" \
    "caf1d3208bbb18fe86fd2b51c2404666b4f7c5ac0028ee137b665c97847f682444036804d598be14b3e81504c92bf294b3439dd05c1a799085a35220da77c04871bb1eb7c7a1c519499cc5970668afb3c270b6288076a9253ced54e69f08639f0c9f43b3d274b26ec091a9a2fa64c2666b15aaff0dcbf16419bab15352afb6aa4d16938376700aa7a15d4d9325ceff0f0598e8ee6488e6bfa48213f195dc5dfcebb77a913422323674560df208f5aa203a80fc41254bfdaa55d9d93bc92cbe09410855878c09ddada212774a2487583c625461c1b073aab6b6289dac7d1f5b51e57fd0b0fea5417fc32915f608e28dd6258995daa6ae72673e04cdce1202ba5" \
    "9518468b80c73122f4ff076a01695bf6fec9714e6683ae93e65f4e61b38955f921dcc8a0725f1c42eb10ef5b2ee1f618c30137b9f85c7839eb65f731e5135bfae929eb118dbbfec009eeb2fb8effe189d987516407fd2b61ab7caf131ec625ed168a17a87ae2bde47520b912caca059167e329173c6cb1534d2bded106ab9c1dcf84b42be1dc43f6582e6b68894b487a959e259c3fb3f057fafbec3146c9a6d13da12a6369b2763ed9a12fc47488938a8d3fafbab7dad2b5da7241fc86292c508868e118bb6b400421006ff0328bcf0b744e2e384ce73eb4141a45f96dd117e3d76142127f0f888f57d392b26c5ce24375530adfa7e41b9dd17b61f2a4cb4dd" \
    "25215b3185ca73628a4a300d3ca01b67bb5d7aa7770d853b8381bfbadd31fb865230b9df4fa3a311730f6201bf38431fa5f6278c84ecccd4d72847df4a1d33fe46fcb696c02d063a422575c5190ec3d0a997adb99eac771a4a63e4d8db6f1c99661de7d491c71b317a34b1b3f4842c1f18ba93bb3ecd12705fdcfd540bb8040c41ecb4352ef2609b7da5cc6abc48da4f85f7601dffbf2d7b79fc17bd758898bb6d11a215124f64dcdf011c35eacd5d0673a6993e3bf336903b39ca918341392b4a054810c62ea67a10cf27b20a7232c86460b5a87e29bc53161e6c6cdf8263d06b300ca4d5209407b578856b85d7ea09cabe3be950933d489d3293abc4bca74" \
    "f333a664da9c5bbea3f95abdf077ee14f3917a28d3de027c522eec6caed6081fc448cfb77be7e8ca6019f1168e9d7b70d11f56fe0b0910a6d69db8c66a41e726c219022bfadbb94dfcdfd3ca5b762e9c7f7d01a90332653b5b4614afba33707132cfc7281e21d52dbd748a421fab0e8145d4039284000a212a51888f6454aae85f91a616ae614454ec009ee5a2e323056a4ce220551b06428be79ccf314d9d749088285d73420fa8d0aa951aabc77611380c28ba402c6184c530d9d5e9c651fb0cdcd465356d3d13b39bf94b04ff0e8ef53d5cca0bdb23d12253c60a5466cf661cb43296bb8ad67cdbfb51df7332f462ea0607b77fcf5510e878ecd639d61e9" \
    "e0838cb59cf40e3ca91f1263ec1082e775f90b0e964b1ff2960c9d1a262be468a1892261437376ae71da5ffd0b62bc6b39c02dfc882282703d26bffd495c4501194e7cc31bc1876bac74064fc1940c300e8851dbca0ddd7888689fed69b93431dc3624316268b0c2bd7eadd2db4f22e458d41f02d8877169fc349540e3cd12795ee28152d3d37362294caf3c84de60e6ad15de383009fed30d3d38be63f2704605d64c9dcc9c5fb8748092d36adc76b56fd027b26d1fd6224fc502bc46e3ce368583ce88d91dc644239ce14df9c3b4ef35857427ec338806187e8ba128fb9cb9427d8f9a75e25773caf422e2be1eabe282c85bff49df94cd0bcc2c2376b45c5" \
    "cc11618492f8483e5bf48d0683467ec3ddbfb37aee29e7d059e207ca9bca89d8f85fff12b527ecc1884fd6214d919c65fa5b0afcd52dab13e542de5ba6742c0c015ad92a7ab3b907ac074509f28beead6846b2cc1272ec1d5a2570fcc030d769cd47185448635918ad650445dbfc1ca20dc8d2720bc053f7a2d1e53551c732f84571e318880071fc75b1385d6facce4cd22b92772ade88a8a38f648ec102e4c0511f63ffa052acbbea330cd91562abb49fb51b62d696323847a6159078a796c9da98c090f921af5ef632a64237e85be15db095bb76aef9b0746021c2df7eef1cc6252154fb3525ed80f82e203c0487dbf262280b74ef87171403b0ac5c5198c" \
    "0ff0eaed10e56b46e6fcbcdf98c7fd7ab4814fad8372181750ed8e9d758e638bd6b9b91919b4b04ebadf4aa578f20f258460d36ad270c92d24a27f5ca3c06781cf414ef1c08ddbe6b21baefc1adb181ead397020fac776037b038fc0d6e7900e481c0f3f8bfd48af7b367c1c04ef82b6ad9f886882e2c93ab285225295807771df9e8c2af26f80f964b424adbdabf99df3f79ec9f15f1d4379abe98a5607886d046d487c9a710f650d192b29ab9cc7251ed6259ddc98fcbe2eec57e09f093d4044fcc68cca9e6e62d2da0218553e75fc9cafbf7c8b2ce1fb40cadffde6f210ac1fc188d429440883648b4be2510da084dc08beeea397578b5dcbe42ab45eacf" \
    "0f35ff1fb2cfe784720815b101596c14e8b65c66cbc44e80ee474270f8d9b6ccf7e2ca46a5c4a381ea560d23a194642c9f95b486f1bd1fdc66337fb04e954da880ebc229a2da3b27a41be23c8e2b8bf77c43dc76e68ab137258abe2b33e0770cb3382cf131797920aa3ddd234f84a91e86a91c5f3295cc37343247083222fba096b253c5da09231104a646016c098648c5afbb695b4437849a156270d0c4a20b343f7ece26f202a5b83c65fd6e20e91e423e03bbeb01bcc75f19578b972c34f692c8f4349c9dde82d0e98140dc339b47043c3a7e6a3321a88c286d800ec37908ba36fe1ec5707f505393e4f13ea9656c1393a9d95e412fce2829ee78bdf138e" \
    "ab36fe4b427d4acb84a24d4391dea0d35782998f55195aee23b03209a2d1f3b43855dee204c322f61bc839a40ff5e5b493ae84ff9ca96668bcea04c0fe5b348bc39e76487bcf0cef5b1987e2d6f6d195161b6150e52ac1f72e7e7b9fe6d1728fdd5f48d14fd785219324bc728f27f0df4f67d345c703fa03f91c0b1904eb1a3ad646eb2ec993082774584bf5b12fc00db0024f20aacb7b299d1137aed0feb8074eb3c1b3a188228b7f52bacec564cbbae879398418e7d1d28b1c85d3c382c89fc7446102400d50a814728d70346d7031494b26d289ff7a99538c8a2a652db84ea0674d9d2db90f27b456388c96b05a3b52d69bbe8668e1d886ef99152e4623a" \
    "e9aaaebd6d301da650f6c507654c3f613a5da0c8a86baa43a85c4472687628739f67dc051d88e3eea662349b0072eb074b293fde9137b4e19e09918c129095f6b445e6fa096a4a942692998dc263735b8f9b2e43cb5112c0117ec92876bb118dd14cb4e15a5eba5e778ddd25d2a93d26afba553f7d412ea8aac1d28ebc7e04fe9e852e0537ec9b16415be6ab59ccb32f528e9c1ccf906f6111dc96060d62d612c2f73dadc99d55822e059e677e523b402120ec20eac53cb2edd6fcd891eeef91e6aac72038f8506be492eca16ac53f1fc4772b95f668ff64e7b8eb4b6faab843b1a7b5a7ab86f5980b0ab7a044ac2695e29b43c11a021f3fa6894da8d01e97f" \
    "0ccf5f08a4acdaad34c76e9ad3590586a23951aed7f1a040bd3510937dbd3f55fde9c5f113e57d8e24fdd691065f83d66316c9a604d38169015190740b9503b5990a5e984aface88ebb471f11fb6c3d51b128aa64abe4bd9615e82f0b911dcfa68a17782ac452409f38bcf3f82074c0f24ed2313fc1a761e47ac669e08cc31b0e73faf34ca6d34add7045cd0cfb992e12ae71193ab8086a43edbb9d06d2c98559f35741327db76d1008e99596b562ef79790d499db890407b16d0b3c68ab7774eb4354c24708410ffabb133de75586bef58afa9b0e8c54b549c0c9368dc1658b65b9cfb6aa7c49d73ffa38f2c64010a3cf25d21bb7131f39628782534f16c90" \
    "599394364b4bfe7b34acca92c8aae83527f12199057b5ca108611a5271f14487ff0226e51084bb120a5b2b22f96e92527afa03f9d72dcdbb73f0fc00690423a4705059f1027982cabdb4d02809d889cbfbb80a2979af0cab9f7c261862509351732636406653db0b145ec08d3e11540673d03e11332aa1d754ae9e83a5001bf6d22cc3bb87394e3dd8020337e1417b6da9eda79a4dc615a95a2e6e277a3a44f953090a4aac5464c8d147a210398f866667b54eaa0eaaee8778a39eee282694c3bf6513d61ccca414c7d6a4ff9024fe5b73d03a2abfffb7db78b534bff9ee95bcddeae44520c89789825611eb2c286bb396e77303a8ecf50c200d3a8133b7cf4" \
    "c773e87810070c390c970f1be56c253d698a2021b119a32823953b71e1facc9dc5309047004edb28f66cc4d5f561a402c41a8ee5c4230f5a58a2fb47d05f20bd23bf461fc7467ecf01f112cb67459b91d59a23fad82d7c7dddd4738862db41d98f4a6a80c9705f719bde797abf8a74711a737fef51bb72f92f8464b21de18889449c8e187b6f05d7408f89526292b7070f410321e53f7b52ca4d2f5366246d330010212571950a667c7e92e0f510ebfa208d4e30f73c0e113a9933fadff6786d3e3fb4563084c585cc4656a4eb677b90fab2c19b0c2393cafcf33306efea329e4b95c8193cb0cfdbac51252cba08fe81fa5c0dde98a8b4d69de57d162a72145" \
    "cd49cccfcfa9b91ce99398ed6f597ed33bbd3736a211dd9ca79da9286f410a61f55cf436ffec7b3e51f6a04420286b02c9bd3a2dc3a158b2d2d5d1407e168506c4b97cbe0bda79ea5ab5d25dc7547efe336b70c934802316534e771e786cbbbba22a0b6fdbbcdca86c9ad5424d26e14edf8f8212ddf6685090d042cc438cd408f775495258d9cb00ef6b52fb98e6b97a37f31710a74d4ce9f323da51c9bef7752b63e06e687b6f7b4bf1f08e92dc310ba15ed8cc78cbf968e30ee8b5f0494c8ba6bc75cbf4e8f0a0e8f45805224f6e8887976c4d3aba9755c85b1400a277fcd1d148b372e56975f82e3c31672f899b7950677d9bd3604d3909d0053bc68e2fd" \
    "012ce3f6a2146260a869024bda3d0de666496b0bf2d06449b1036646e44d70c0ed218c4bb92c72c5e56b9d90e656d5fd82becafc02ef3a4034454d89f049abc157aece86e1f34af7c0780f7625da847570d3122a6c07194f90df40ad8ed1f676d7013538aafd4d6ed02ab27c273c8be69722cb07acac63c06d3dca120e9ad339c1e55ae172cf0ca38ae0210348f17eb98c2a60243333bc5b1fed54680e08d4b2cea79a11e7dd0b3e5724f5bc399dbf76b6567c009e5185783f6a7a1feb808d5a53e49d3a58abcb87cb858af74795d0a6ac33791d4c7a51903241a59a55a64fa8d818bedb73bfc0186e7e6b55117e54a1e44de1dadc12a34b9eef6177aaee9e1" \
    "6e1b08965978d7b78b66c114615bbae20e51230d9bbbeed02dbd0282879ce1b3cf74887795299702119fb175ac2e26f8c350cf09a79d3a13e8fa0743d30d929739f4d33872368209a2f97e803b766fb5c3abaab8d84f5628710bcd0166e745b63303b080f987e1f5c5dcefdc151dde4098c87cc336ba8a35505a1c65491443374509e8f73004fbed03b0ce324209bbc2c9110dd1c9c41e630e4dbc17837ad143f76e434621961a1ae2dee129cb244e62dfec258b9a5659d9324e74be1c033a02d29a8915d42384a4ecccf16ab754de4961c38b99b05984c044c40e021d96c49b5df5820b4f9482b2a9e3c59c0e83b59ed7fd08a213b3e73fcc17508d8d1ab93" \
    "720e8f6d19cd25c6ca08b2768d998198aca02644ecc4eca7f53ae030474795ffda4d9ac0fc3c45afb592ddd761f7b5335c13a6747e21075a760f3ef12da9aff1670316d6cca51c4875c2fb06de814abc6440dd8325de32fe07c4ddb5dc865e0a90d590190bb63e13732fb68f63c4b6865dbe381ba46ae42522e24908d45c24cdf01b730249de1fa3462f7cdb82408d43c0f242885a459f424fee1d74b5a9989e0d6b5c2d079b257a6748da65ca73335706738963b7fcb8e7f74ea763f0ed2e0d313ba7e3b56c040b4f024bd89ceb4d42c6c879385dfee578a19a83510695599e0412d2d0e3cf2fd865f23d8e8a073f996a47ae70bcda9996e7483de66730afc" \
    "31e77897f03430d54549f4c0202558ecd69977597450e49a520ee437eb35da51eb8d02848a4462121934fe3dda654cf415d3e7b2687187a45f6d310a45b6abdf39bc33bc847770fa29aaa917be69355a7bd933ba91377bfdbc1bd41d1cfe67ef41fa730685d243d69e325d157338fd672f32c13994aaa6ed93a033381916f4c92bd22a2c355fc1ed9f558200a2da8a605a69fbf71cd2f1be0982b825e3053cb520c9c0f43d25d389559980a0f258c690230348bbcfb844b6484bc9ab23d325fb48699d27452c62f0e889c0bd0cb9973eb38a0f4f5563881f7882d091818999e2ca392a8df47d546b7faaa81f9705e7b13186ba7957dba33fc0b034a0a42e7fb" \
    "3cec1cdedf31f93424286a18d3c449d32c67db0027d297f5f495c5da035cabeb77e8aef10e91a05bd5aa414d1a37fa1099af959b26e5403c63b0eb359db664033001bf9bf7f779424ef8c67b173bedb7ed4811d50d36416bebd4f9e923f08ec727cfc51c05d3d27be28c704f6550733d99d9e64a65362a28df7a5861509bbaabb1bb661db2a74a5d42edc5168f06491611cd6967a97558e7c129bd3a8e084625504d090da8f24f8ae2953b8ceeddcdd5f7ab41b954645c2d336b6ed146c6dfc8961d245833356079440b59ff1f377ff1bdebd5bbf093a25da8a803c20567d619f5745eaa0bf12bace9b88709aab3edfdd717bbfbf883da1d93780299646bc77" \
    "df10b0e6f7da5ef9a36357928fbc3865ed5a75ad5f6a551d17643e1a3ce3332790b49ba1512d44ac5dc0a76d99d06e7a92c2338e65588b82dd3a4378dcd6e95afc6a8e83755fcbbb42d902697f8ce60416d13ecb9af9e6b673e116ac3cc6e6f6695b12f42d19fb0e9bd7efee0b9aaaecbfae1dcac6f66ea221803f1c255c33e420afae5c3f03dd8eafe1f76403a2c21bd68258f5b1f62b2e2f4047325e40d70d698deb2374c47821c820a033304b3478a27478b322a22643e448b555b119da588b1d50b19405d5b02cbc75c35a3e0aea6dad046be3a266c789c111ece49045acd089656e676dfa2424dcfb7d48234c5b7d558487ba9df3a466d2e461c04c1ff" \
    "37ef6b2c3b4a5f163f8a8bcc7c4a100b21c93806e703bd6c0c3a4b41b0df67014de8ec0164554c257f0493f0a946030d7908f8188cd251605e85e0c82933541f7387916d0e02373e654e70caf8109e3b121720e3d9803bb591c2971fe19b29984d4df3c5a4eba0efa6ba9ac1c5344222a1964b0f59b7ccea6a92d6df7691480a3f9e7bb1a57c09a7a7eb8a6bbd2b8f429be8cee189c3955d3d59187d54904fe3cf1b91a7ac2de204ed53c82f3c60e61975a13500e64e25bc8e97e4800822a1c37027ee1e159bba75eb85cc92bf6ed715a33205e3fbb1ee56d2c1b36e1dc2de17c755e99b7e20037926f4002cd2bfe2d5b91dca1146895fdaae891dbde1eb656" \
    "f39280c9632654d8d24111b5402de99c82be6fa0f335f0aa676307bf60126c8185a00df94fed60930678f76aecc455c6b80100e345e8d7f58ce7a668d07ef86c18e92cb1e2ffcb6f165a19aa39b8eab4e3a1b7f3734af1e401ba9560942b011f95b3067a84233e75ea30a0fc8fd0516dece7bd57e323e782ae24fd2f16e130a0e547c3db9d2361ac6a41b3e956d532f9bc1b3a97ff3b60d47b6f065bbc672df9eeed8a5d95c5db1c7fd77bf8f69034613a85553c2e5905e451e1d76ef0879f329aec8386d5d255cd0f3820b1d7c600ac4d6c37cdd7477eb916c499f019072e51d08ed7e1c31176c803adc99c61423ee2df1a08d264cb725bb45e73679eb0836" \
    "07819aef3c84ce714447e9e42fdcb950cd7d5efd43cae8ad311f88e5de94a466679d62f464d494fb9b9f3c82a1128ad311ce6145ac7b76d2817d91259619d1f6cbd0d8361b8d157c049546fdc07222f599895a0ec6db0c362ac4b26e46e70b4792b06d1cc72aca730dee8bae14581c38c3229bb12965f368aba94f285788db095ab084210e4a2e6115ff8d2c0350d10d3d2ec8c55aa8e6ca628fd9fc4e7bab9c8255cfeb4757bbc6bb3ccdf013d8dbf3560243c3c11030dc1dece552924c0771b814b2c408cfed347c4ac082dc7cb77bbc51af2503387c2e0c44f3b3d95679495a71bf53c93f5d0ac79e075cb3a8de16ce716d71779e1330dc2c87a87a376b5" \
    "3f80148031f1265ea3baaf4f63fe9ca550af5f131b49db074fc080398fb6b7841ff280f6a70e5923336f63be7d7bc06a6f053fcde40c3be6afa6c0a1de37f0a940e6a57e245258c7648042e9a219c0d8d2d2fc2ef82bca7a335cd0dafb8ceacca745cd413225eaf33ed695f95940669880fcdf5de10c5068e5caf80b6e1f6d945ef53e6658efd64fca57a3152b587852816d30822719955bcdd9805dc05741a96ce040161f18e5820fecb6669fc9bfadde0b37c750b960f9f26faff7789b2db4d9ec1d790d08df35157e14143dfb03529ec03c52e6537aea5c75ce011e55fa5dad031bb6ac278c0fe5f306468d560ce9c973864b7151acd713d425a53bec704" \
    "bf10c84f684deb3b98635d4241843a119680c5edb771abc682072fc0956c85727adef9e601b931eda002ac6d765288c8a81720c2a821672448a399b55f7517798e794b21dfbaf931b5cbc2487fc6e93e51f8fd85f19ad9814591049b2a6ef9847a9e30754ac9bdb24a1d2355b667e7fd2474a09a2c547f47f95de5048ec0a81dbfac4e72eb4bebe9cd753427c2abe17f8038be91d0c4c502e478df63e500afbfde31f98d39d7f032b07299312d09825005a3abef5792472c8770484bc5b57ce556adc636aef48747a383b7044e1736f915540d155913722f62b2b41ec9359c28a9ae3901b3080d7317271213ae4b7bf54fa836a63deee2a606dea77f482789e" \
    "45781c6710ea8ef5f8bdb3ed1d61cbdbf153ecd147e7af51ad44296cfcb01d2c2d0e6f306ea4dc967522e91e15e0198b0f68634d2a34e35e86b9d06a2da4ae32eb63c53260e7d18153a8fbfa49ea0899563fd127344ef31a92d2c7b7aee69579267f04b60c3ad5803858d1cae20600cb70e21ca88cbc454d7a99f69ba8fe38c9876b16049a255059cd3854d507bd69eb02592e155b0643bee5164660437501eab62ee1643330aad5b9536a65e196acbfb7aaedb9c8b554377c509d4ca6d157a35ad04f1effe44cbca4aefcc098192f1034df43dbfc50df7ee74fe5a9fa9da1bd1b5a477925c89cd63853f32f53ce5ba5240017c21e5f4e5dcd1b04bd665e490" \
    "1a3d3b0becd6503eb1a4935fa3a3e98482d1350b7576a0899d6bde4d1139eb634974374362141eac2f598ac6976f04fbff722d802cffa75fdab3c6b2c29e45021a2b27a2646e6b7246f493ec42f6ce6d32b3496ebad96fd50f4a08318cfb97f8f6a29aad967dcd4d93062d5528c3bc74c715272ba1ac7085958f113db2da4ab4597afec96aaa9a7a9e1ee585cb6e458f2708354b63d14fee1803802be6c2d3c0cd24d28a437d79a5c2af2af2ad5ef038dd1cf24283f0547b0147d3a09b4dc9aacc30a464c37ee13b9b278c20410e52fe43b3eca5847224b8ebbc6a2042c3a2ded11ee2ed6d2747c89228779328f4d43c057d92f8e7ef473431d1d22f7fdce5e" \
    "976401c98a2ff33c942128bcfb7bafa9e9cda739120b022596e389a2294e209371664cfdaf77f2bba2586273a9fc93c82744b0d12b17d4ca51b5130ae348b93544bdd6b38fd1fa617b6f3d86823982084265fde023caf3cb3a3ac1426d1320add811a7d470669296e60dc1ddcf5b04d101d7954c404be68e1a1b9d330fd6dd62f50bc8469b5e42c2addaf760d7899f8b2d4281ffcbc3357db800afc311ba79bb635240f358e0924d9680e6f8e4ecdd9e8e50c7df0b5969ffde8ffedbbae67b22e98f17c1ef140b9f6aa4968b3cac4573eca771d64a36097b5273926453826bfe516a569aa7233420f0f1100228f05f700fef86cbce819d5bdd52734424b8d2b" \
    "6618a0465c9359539f20c5b46f0e0b4febfd10fa5e163ae0647d5aa6575ae37b4e298290a9d71b75036a07f3edca5cb86c3f4134ec904c3e458a33dad8e8c225f9b3bce706b0021cf865385d134672c6ee4029aadce8b645dd8653706b67b1b1f561cf9817b0a5b1ca8cd74e93f4d601feaa0adaa3a2119d98ec29d5737a3ab5cd9e3b52414b6eea164b7546d4680ee029d78522d53ed6bc043637988572b597eed370741802c61c484b92e4491285e7ec432931e6318e17abfefd2805f3baeed5ac0f9c105953cefce7a0958686b39fa29767865b0c9046fca0fb12997fd3112e827928aec1908890ca3ed90137406e092ea08eb83295a082c6b1d6a46976a" \
    "535f14da857ddf4cfa04dbe2d4d9694d97c8394b9623606dabacaa1e2bb531e119862eda9aff1090a97fcbf10c047397879309494fda95c5c11474bc542df41fcd261e99b2bcd35d00441b2120dab96a18ba030bffeef0e8b32a7300cef407abd5078b1fb3fa5139661d727bf9a46451b207ce988ca89a60e7b74cf17f52930d9bf11e758702b1af43d078057da99bd1bd4012f8e050bbb5c782aa985091c0ce85ac7fa2141c1c440026d6c995338774a12e7934e12e7a6dba5533fb29f8b575fdff55ae448fba8203e734cf2a884fc1c699a9537989001227f68f24f3ce9b8a6ab449a2fda5b2f0b5db391d22f11d4095494a5d8fab752b782e671b945c999" \
    "53491028529a42d167ec98ebd67b6167a7405055b0ada004114c563e6f6ead81fc25f295fafd5527dc77bdbb7df1f64f6cc968254d45fc9db63832a8fffbf80af7ee5653977804aacf6b7c71174742f3c06c56850d482f981cd30651e9925b8cecfed5f1a69ed3c2b7546fad50dfc9ed588585f57f28ab8bcba93bb99ab62a8031d3dbe0a6d635183aaf01d0b9100da48bc17117216c12d129275d50a1dbf79d6d19f2b116b2cb13bff7cd8b9eac80b1d09cc23a8286d810dbd9e5a78d78453cf51d84e384b8e83dbdab4d2e9ff9c57ddd63d400210d7db35a3d6f3ecc0f95d7706b3ce86f5d2f0eca55eb4a2b8c4e90f8d330e86b6476411ade5486dc266c0" \
    "5558f75404513f1ff5c74325edfd87e73b9576353e0304442941920003c412a3f2b06b87b8481f387ea82bced1b62f7aea56ce5e32dd58a205c9a6c4b6af462fd474d910acc0b8650fb0de5656cb02c9a2380331692e89a62eabea3b8f694a8c850e0796e8a254cc31472367842449fdeea3dc55ebdce07a2b51230e95db66e18de4bdc272d739956bd5c3a664aa4b3d53ff2373c0d0a54384211ce4d1ede2567260c53c5446afe946c287bdfd4352b25bb49e32f1f3202cc2859c6649880515bee8e6ab96d600f04976345457d8a4838d2a163b842c995a6ce46a3c07921843f8e6e7b73e7172d1fc5a95127b528ad971c95235846257f80aa54f0d13f5630" \
    "ba9c1910956fe4fb5e7d471a070974cdc90fa1cc9f67fa32c2432138173972e9358e1ac49e564ddc3934d8fa53e9132b371233a9fe46ac51e43f27e413162c1038dae001ff48d6524872eb8caee2684879dae755e550b05f8ee4d57f5553c6384d19054318a602eff4bddb4b78740897f9a0195ae524aaadfaeab6845e50f5e3eaaef712aafc5827d68c44b1311c68ac4f2866239e20ffefd0a7477d7ebc2f858a33320b06ba4a7c66549458795a0cf7d2ca3a4a40d42477a8a104d566e3d7afa41c4276bc7e5e601cad669ba19b6a0d3d1c2229adbcbce7eb6e8b26877682c4e0e0a4e05ca71875620d28055a8f045ee684aa5c15592db3017626eb50d2b55" \
    "79916e5f237d2ed2eeeda552ff473605f579a3f5c18280b6b834e748e6386e3ea652562070e6050ff1bcb6a76100702a118d34da436b7ba63f95e009a3001930fbda2b5b910fde8587126f4722da86fa692b671cef166cf4edc3b379936e1471a0b056d63100a27dd67937faebde60be26dba3826c8d3ce9e945ca605f894749be5c3d5af6c0373f097876876412e6bd6f2551d563d8d1cb5ca38b86af5a9a027d674aae88568713469895b7348001416d92d7dd7bfd15e26d6660b329e7f6e30458e49c90cd7941b55ffa520430979047a99e625d06ef784515b0ae783a41337cb772eab62af41080570e207b2891f326f20e2cb0fa46d30b38e240425b653" \
    "b0c0d5e61a177e2cacc0839e84272d8b232f68f021de2043ce858603130504843dde00fc9fabc2ab5c4f9e47400165315923c8aae4cc510fb04fc9149e923d49217bbedea68ffb4198db2758a5e1ae9646f4d65f6e4ab525886acdd4f16dcef72e123608b944a684052bb56f3048884e6f0af8aa38e9db29b96f0ac0d5e81832963a2d07625a42e71399ded7799670be43eec5f7df1a1180b5e5166496a1c7700c6bfa571c416eef36adfa4ddc6c065a6808c4e4bb6c26cf1035673cce1b4b33f3203474519a6900f0e09e2ef329a7c74df15bed784059695b0883c5e6c521f2ecef41fbacb5efc0d4da30e7385fd3796831117e704747e3f8b6d27c6b3fda3" \
    "15c31c939783461a354e36923269f27e539307c044dd160d37bc8f9dce5dbd273b38030ca6e865d3ce3a49d5f4847f39f5388023b6b8f329c46c76073c139a93e9562ff3ada3c30d2238653f807eaf50c29903a7043d14bb30c3a8cbd97c9dcf67452aae755b68b177711138a00087ac03df18b4f81380acc1e8af536d41cdc3fd2c7ca7c6b95da8160dd5281ab21133ff3147b258e33fe2c0041305c0093358f333ab446765a9d847333977b73b54ce00b81909ed545a47753e5a4b997dd574908441ef2206542b520bc68d3f4458664c9b15227f0fd8c227bf0e8cc244bd001d44c60fbd4467887ebe03d37a7426e12c03c463d6bbc13a1faeb62f0107f3e" \
    "5e29ec00b01c9e9d6147479af3074c529e818ac35b9011e99a634db9e1f6e7d0927b8b94db63ae2ff5c54ae8a28eb3d24c8015701f189f6c602790440e420655634ba383ca4425aea9e872ccd2b8297bc14e74d2d47fa51a97ba4b97d17c6b3b350cdc64092875a7f22357bde01e1dad813f1142380fd372a5bde83bd82076d07c519eac14ab1e9a62f84212772af0e5f0e4836496739b131e84ee868eb8c9d3cd9c52c27926910470f9fa80e46943b3b4d133b09c357c6a66c1d72e61bfd4a39d5f914db3357d64a08ac98fd443a6a53187ba9ca5bfe7f712d72a9a0da017de601df2b43f522439763d4775b3546a38fb7a80af3f8d7e27a747614fcef403d" \
    "2ba49cf8c89f725f17683ecf90e163ecd771c1e5ee6289faaa88503b63246392f0075b03d2fbf133b05e13270410374f1390efc32261bdcce7b329a63e3f12841d7342d5cacf45c64b8f7a081f8a6ad32b5a592bf7bd1b621a3b29def309f41c9a2e79f516e41620d1419cf94916a580071828a5d53d4ac32c69776aec4ab2614f8029eb20020d4a28bda082ea7e905f901183b924abf3f703853cd28fcaf35c25b37a404ff0d14b3a4baf2b6a88d277ac8f93f04ccdbd0789d79f9f46506013020e937b0a780b2bed32f17d31fd13d144d87fd1b56b51faa4a6c95878a6a190d0d89d24bb6063f32bbc8dffa7a4fd73413570e5c84f56d83e3ce2858c925dd" \
    "b755abfc4c97180aadb2fac3a3447366789ee8eb2eb4075a93edf11aeecdd3cfadbdc22e29c730b58e5d475b441ac66b5064b00c2870556768cd87e5cff4fe8f7e8a5ed069c2eab0530f311f7349c36639e94ef9d0567a046106f52162daf06d986ff49b8316a09baa6d4a78b77df4d7b3b1082c9cb2efc22b2ebb565dec741a99c305e81c3eecd7f2ebe60f6703d5504c408e2d0432211115a96ced07a5d3e6e118153e8ba839e5ab0fb64c2897ef30721c4363ad40a881bf0b6c6df693aa830cf3a51767ef1245515d1da762969d18b3a8ca78de5b008485c94c41a142625f8bda37fb1770008774389ea9bb7c89798f7a85d53e0da3aa18678f10ae1e85d" \
    "cdc30406230d77f2c8236abeb89d61ed36405f7f132c51c52d56a97536394afab7c9a40d54a92089519dbe7b5542fc796efdfb365631dd53f5b57177268512a1beb7ccbdcbb1c176199acb4cfb0e63e64716c2a9a3574589ff89161f632b09fceb75c43e108f23612800db5730695ddaca73fd018206531155bce1967495f7b345ecd4b7aba90ef087b934c47fbbb1fdfefcf3657ba6cd93ff341a04e129a46ed402445025694ace3dab1ebc6d6c28f9eb9aeefe179f7cb603db09913351d7d4a1a05b3304369ea152c0e36784e48a73993334f3dd5928236b97f663f1745a8db3af6285d377d312cfdecaec4b8c9f1611b00e6d563d99823f5228a5a3f9f34" \
    "21315a1711796b1c8bbef1a734aca2e875afac49408b1967a85f3e87dd24a6b9bc7bc601c5afa006c1eda1c260a0701717cf79e8f7d1ee9b347627e1305ce893fd98ae7b1230b88a50187182b12acde7a8091e4873ded58d68c873290c4ed17d750697d56fb31111c6bde55aaea1f8e4a6dafdda3ce84ac8b5d4a4b1c970fdb0a35406c3369d4627864c71dcc1bcad98a4b39d20cba4dac79c19313de079c9f818ff6fa72f55c4462f42ab6b82c1486e222160be989ae2249c04ad0ff9bfc29e36675703827317f8224ef6997a5645ff9fb30d063c111d4a26257cba6dc9841d9c3a416b088bbdb7ffbfe7e910f242a78dd6e69a2ecdd8c2db0a24cfc50d6b1" \
    "0bad6b33ff9f632002813f3dcdf1bbb006d1b81dcd917a1092"

#define NIST_512_256C \
    "584af1b7aab0ee739bacccaac5058187755e77e1f669e910135891ffd794808397b24deb33a371d9982af25089933f0da0a35b1b8fcb3ea2aca07900ad90181aafcdccf47e8e4a801077eeb45255a4df280f083daedaccc9c5ab5a52cbf2bbd1a985b8fa13da3f110b7a08ffa7b277a5158cc570dcfe5b2e64607e20b92331508cc157247bf01934921b8759111282066f01d9dca09fb27894a72c90008c423e6069f39b3d369f90ab42b5e917dd8bab3f558da882259a505a68abca2794b6442e64d287e1169bce61d7d8d8417c5b3c8d7229fd0af8db5ec08b44f7b6a25409fd9c3c0feff7d395b9c2394d1755ba605f3ff502c1803d49cdf93f3f3520e53" \
    "6d5f87b5bf041118ebdeb207122d170bfbfa438e02e2588ba8998e4c92d753172be60d6946c5b1b61743bd46ce9584402b4893cbeda508358fd517abe26090066c1bc94e2e9afb9b5e6989f65f453ffd146d647c54b67f7cc300d4b45a6441ab9e5f4fe6cf1a4b5321cebc784cc2869d37e73a21c0bd4acbd2ab29d87378e471433f15c5b0ba2d6811d1d95f3f8414ab1634995eda2fd6ad4f429b9ac604f4e1fb199f6d6c011e34af11451d700046a13fe3e675d964cf9b9955be7dbaaeff88169d51306965aa534a1ba435b6ddb919f553b629671272013152f6f3c9bd60de3638efc1317e3e4e834f6b3a4c62d86007329ccc0baf8a88a7d8c98f8bd6c55" \
    "eca6aafa24cb15670eb2afe8dd936212dc5deeee02fa265ac7d45cab37981a97453a1353613958f84d24cf2b2c5de2fddc1d741085b819fc722286f020b2469d9527af4ff3e9155d4d913dc4b9aa140fa7b9a17a717c39563370f2afdc955a2d857568380263b25fb701e1fbad05620fe63c5f73edcfee32b0c5883092c9bc10bd2d2454b53099c6337ca31730f333c740ab95442137a056942930ba6bd4d60ee457cded35d7305a680b6b6269fef0fd5e102b36363eb78b85a4d2978f400eeea2f94a49aae0e1e3ffb5212281adff7ae772088f546c9b992b3f560d2595ce7aa11d83b03bd413289f83ada0a088c90684da1697a248b4483001a46556597d7" \
    "886ca606c10392df2f17bf724ec18b668dd4f3c98495a6b6039f3a4e7491682b1fc09c9c4529a99099da8e8f690e42f6a99d962d8712a26a8f11b3fda275347eda9e1a6ff297cbe354a0f665db2759ad2608070a040414ee9fd835b88179933f3355adf66bc69043ea0ba5aa37b516069dc4d4f38e1264ceb0833e137426fae8d497c5c4134e8d3eb49b0ad0e1202eaf7b347e5e87a618676b831ba30cf5d20818d5006d8b8829305eaf945e79f109f448d771bf8347b6652b587ccbbe7ebf198a8ddc37271bdac542e9e0c754c01e61713e3daaf36fb5346a83d011fb2a28a9a432b7c58872487a0baa6e9023f5f293aec950857a969b51c395940a6570951" \
    "4f05431ad3213c8ab13919c3d4a0b1cf73c1958e36b44ef39a0fe57096ffa9af7f972c8329678f1e4f51ff84349880408b3ae9559480307789d3e87b38d1080df1a0eea1a282a4ac41aa61136a4f53e34afe9b44bb349aa8b02c6b48d4f6b0d16ec9925a889a039a50ed4658beecb22277b6b342f2f911eed9c375bfb2952965beba1f9821d6355144c2b73b78972564dc09373980f71fb1ca3f0ec819d7f92fa91a9d42b75fc13ae5d0bba4df7a35123fa03110ae554b594c4a3e4b53e4aa99f7911540905d2fbcfac05a7b3cba69926922a8afc43c1d4e27890e30a6e3c4096fc98e7af4f7083e4d399ca8d7824a4d2238a5fe0ad31ef923a6855f5bfccde" \
    "9da6710d72d55d22aa4e48a13f8f85fab318a2fe4c743d5c00849acc1b9594fa00016a34282a018e7c8692ba5e744301560bf4e4c45b3cb0c9d19893c0a1fd196a97c50a03a005fdd816f8844eb8f45f175800a1bca4c8646abbf27b99479dc339d411eda9e9c3174969ea7d94e0127a839746c3a9f3590d4fae28b21a18df7dfa30e16d8f69d1514d1a0924d56c15da374447b910c977120522bbf5a7783aa02858b3e828a2a9425f81a51864cf86f49ee974008589aaf907b42ca4e5e847d04095fa0c0a16c350fd4b7ea6e78cde6016e16c188cd65d48e3cceb4e3a0b8f94df832447b848b803a2d1c67ec21694835be6908f7b12168815f7885038446a5" \
    "4519ae30997caefd0fcbf4cfe790f3204ca4371d3f4df5f1d1aae746955156095536796e04cffd35f475e52b490e94f3aee9280646e90af9e5e6c3ff815012aee3153b06a2c5a1af52f59782f9e1744bc255e5cdf6cd880727dbb6b6afc9a01b597f9dfe5da8c2f39211b4dcdf51baaff2af167a354096a4fe506675070328d81d3c46601cbe878a1a92e142e3a88fa8a6c16313ed8b5c56d20e7b437048d36e9914e034c75119fb543fc8baed2c1abd445172a205f703a80cde9e29d5dec86433cf108045a7a0cea6e2114fe52784763528ee2e65cab31f1286772d1b0e30425534804e8008438c7a416406b3dff45be10e7dc0f54c93454dcead5a2b20339" \
    "1660dd8a55fbe2abc372667e93f9d93f5b0cac75f9dc7cca12580e9b5ed5cf8d8ce20bf8eca107ee64557c5ff71a888cb0b267513458185bb0362d248490aa89ff436de0fa94567920c9c2450324afc6558e82fe4d5c3e71c4d3e111a28716a6f4216dd33e4a60c49f4bf2de568c9174c00d99cdb35d51a4b6dda4d3370da67ce1f8a63ff647b9692658687c5fd6e00076cc165ff4dff45d0c9fe2f9c0b8dc747f358187d0f0c2cf6c7bbdaf8d781e01e0368325905899134cb745e5cdfd2b15f2749a6b4cea0f7fc8224d087e04ade1a2c95aaef46ba25fed903837bd6f14da02125b2ac8a801f2cfe8a0f79fe102382511275cbf6dc2ab65d724602d731c4" \
    "914ab4e76e29f5cb0ea3b43fd61b1dd7ded9a53cf5ff35c7e5be8a4ef8c9dc3eba0abdea019545232bda6c09a71eb720b72c17a773470e2512641344659638e2a4ca0a666db4b8500a097815f3ef272993b22f5d4fb8ae6bc5b7d5cf51258ed9d6f06101bb70987a339aa10ac276b518fdd3b70791395fc2861f9798c55e254bd8e68b63f2af2bc82ff3af901c9ba8167af7754c3fb16752de042347c829475f331250351a5bbb63857e6a510a464a4a948633d5630a0f4254ce3f83636e3a3d6ede771f3c5b8e73bda19af2935fe1ddd2e8b749042b9fbb71e5b4f49d15470e11b1cac85e97ec1f60c6061ec0ceb6f6bc85c9512bfc5fe4bbb149437e06b6f" \
    "aa5f20fd98bf71f8ff554777b987b11bedbc53395df6596e6bc9bc8180e2acf28b10b0ff9c8636eec04b3b5b1234e395db611bcbc284e8ee8fc09f71a5667dac1bd6392d11fc3205e154a8869693078fad6cf2b6f0e9f8d130264a0f25da61eec5162600997ff7e0cb183b84b730714bdc16949559a40dc8e561589482bd0e4d2f670404838ffd01f5fc50cfe48bd56cf0145de17d319c38280827bc3c9cb749a33f5fb360bac5ebea8794d2bf03886581ecdb25cc213891708153d0b3e81166d9159597c17ec6f12130543797462ec7f9e678ccd6d147874773599c992d81273970422c265a84c4328d2b691db21d06d0b7d3511de05d6c2554955a5cebaaf" \
    "d3cd5f1eaffbc93e786f486e1a2d5f794aec7676d11dcfec2828bb3a46f90e36b6bbd015ece3358bd971cf32bd7203303dcaba15b5305802cf7af210551bbcef43eac0ce2125d67b8fb5d0cc22b3f53d6e2cb1da64218a60dfd2569f793dab22a3e19812f5c79258c2c3b102f0f81de8069ac38f87f84c4d7fb94fae5b65c517fd28bea910d353689924dc9dcf4763792d9c58fac5bb8513d7b64507a29ef1167a489c5b1b5000f53d5fb76569aaaf370abbd8e5c7741ff81051a070f7ed176642c898f0be478145d6fcac216328e96bc67eab16352a01455212c8b2025c20507c301c2fa0bfbea08b84229b68c9f95d886e3955b6e61341c48226956af2f21" \
    "c51098fe16ac09e50847e81991e96c7557911ea6cf2af3d368f2820e0d8b77612e8d959cec3530c9cea7230e42d963b9bc1f22721928d676ada8c1f5df3b494796a2be2be547eedcbe5e899443ed23e768796563e3e887926ce378cd264f0359bfe849179c54b2a269c692380f950b630f387e1899da95bb293b0cd08d2733fbecd6ed0c6bdc2abf5387c3662051a8d0f2f4c2ecb58f7f656507f4cc7e6469c2bfe70076fe4ea5880e0aa3ab00b38a95c606da7cb167a305a2e2d6fd64870322aba139c3ae3cb190ebd7a9733b2b0f45eb172b253803bf2055441a0ff9ff9eb0229ddf8f0626dd7e8f774b6b3a38c545f48e4b9293e4125a1ea43460893eaad" \
    "fd7258835908d97857b520fdf885d4b3a54d4b2316f795af741abcc8bace4a6261be0ca53c7e16e6a11f07d5c9018ef879e92d58e2533d7ac70a3390ddf521f1773480c7626c2c070e5eb0a7efbfc40b234314c055fc436ce1e2300539b3784287fd3c4f947824c5e89aa3d933667dd4eb8587c33797ae6f0ccb3b8f95ad563dd940c8a7984d050775fa69d55b9ec23a19d40fc94fcf876a8eeddd96bb8ec3cab426ad353691d7b4ffa789012f119a28f45b333a6649d544b06f9d8271fcc7d162d7726338eda2b6ccc98bc779650d83c53f7b7e44b0a0e7ba7904bc809f6b3a297a9f9864086ff42487f88eff422334d4ab6ffdb1aaf13af43599aab021b6e" \
    "d5237bc3b848b4556510957bd8a51e52369c5981f75dfcf25a5c9e4b5c827b1d2243752b65e1d2dc49a7830bee2395a38ccb57d4d57f94290175d6d45925c62d2e9a2e870bb672e2646fc0cf8cfa38a5c44a4a6ed219d5263901abdc3d465d3d3e7a007d1621050649ebc71d319377e751bba9c699975088659275b9557ed0cbe685736411dc19b67eae1eab7879c3d6c971ee62788296be2baadcf25e39a137cb2f2fd28b22218157292fc0ce37bcf2a01f90c91b561835dfad4a2da4014f2f40d97e4eeeadace577df8313af37b3d96a172970deac459e063c35b1b3504b10dc36f74fb8d92c616543a10a980458e97beb20e05edfaf4543ba382528b1256" \
    "b11ba134b863f10638408221c25180ca17a1e0f9e087ac5d9fcb9b9fe60ae5ebc75c55ad8b33a098a687f5edeb30d5fafd9325e10680829aab5bd43b3f7a267736cfb565ddc746834971bdfb8de3ec2531daa94cdfa023b55e3376ddc5a37c03e8bce6e617e58cd0084802d311336c539abe93c5d3af38b5a29aa80ee04d9096c46b13b89f561a86ca52ebfedde8fe8c22890bd14a7468a35eda9255f83f0a38b2236261dfe297ad79d9a1035bca49d9b0813bfaacb85c867a395d3a754291f19a2dfb6b3d50ac4efc234c6af2a0f6412df049c76143bb66dd003145bf1ecdca64d1075e236a00703b7812bc0934accd7f1c5dc0d1dd2e4c717635ff3e9b67c" \
    "af957aec0f8f63c1b1e221e800a4c14848f4ea06e644e5d3e1de592ef5a8007fa3f07171b24bd07578d68963e5cb1d56e45cd3958835def47c9936f9e7c9754601f296bf60f870a2d7091a37f672b989389e3510794d48d6c5dc9f5920aa6f7068104d1da211ceca4afe66cc9938205fc44d610010179deb7c2cf4c556e7697f44ee1724ec24356c532af1aa7487dc3b05cef9dd030158b2fdeed9b6f0ecfdd316c0876da5ac6f097e134d49eeee57bb7bb7621fb8b6f3bdc9a6b0a66547971c5c5c10406516b6122a5bcc338ed82d41a47b3c30b785197c7df90c3c4a73bfab84054445b0ffb526e64900efcad1c77e0eaedac87618146f793a6eb106ede21" \
    "12c4085f60fc3d6a8408f9df72977b0b118b6e03f7adc8f1749ff3add3132b8ddc3b277d9e80fb526b773d5b23116639b6127cf1e4c4ee4047ecc02f94fde7e61e8cf7c59b04fbb12b9ba4ac9684a7a9d566609ed50ebbda77615499db94ddd6de9fc160e1ee0630cd5a78fa535904027971623152f3f7680ce5f9143140d403265ccc76f8a8e477579eff6ce3f646eda71ac9d3e3db69910f62f5c81c699315fdab622e66985d2dd44e832bcdc535116949dfab112edafe87bf91dc2677e3b56c74c9b0b52839fa49524a5e992c9817c6e6eae2635412577ce41578d7d28c8b799f4a256cbf3f88c0929c2ed09538a6c7da339f62b5d943f7b9c9c6b6e2563" \
    "e2f142db514c4387c40f5c3c3f967de67720b020b94b9f76afe25f4eb4b10097793bbba8734a1ed81d26506449c0a5001d1629f4e83c933759c13e0121ec26cddaf7c39c454bd233d7dcaacda42e6571decc7518fb74b560cd668d361b86148198a40f193fd80a558490afeac7263ba63c92361f6b7a928d6b60d1600a05665d22ced2b1db5523a7b3e0e44e3b4e9437a725c17ac0b49717c43eaf1185e088bb19e6d2f89079ba94e65bec6a690e0b80bef5cbbd93b95f9a585e7abd17bde825de7a6450078c3bb78c502cb1e8fb0e2bd460995a4cff388fa85ed8e527e42117f0f82b5aa923238a266c39d7238c18939814ded3650cde5234ae2e0c4ef9b02" \
    "bf1fe8c6aedc51e87351e782cb137b7527a80f0ab7468ad9c7dcb0ea4e57501bc41ebfc135de8692948d58c351a9476d2dc137354e37922c8e443df4193ccb253714f1ee66213a00ac22fca72b818b3af6d6acb623ad4da6228973464d2973e7bf0965956a2cd6f86419bd788224b0a428ee58d55f2f230e28b3382711a3b02b050603fe6887c0436479827c7d181f736c1222da2a467c2e4bcb76e18d34eab7b112b37189bb62a9534a32fd45e73f6f6949f20cab78c0cc31d814baea6389546a365d35f54f23f1d995b74101187760c89bb0b40b5057b182e2fafb50b8f5cad879e993d3cb6ae59f61f891da34310d3010441a7153a9a5e7f210ebe6bc97e" \
    "1a4e33fd34bb8a14b4db6dd34f8c2d43f4ab19786060b1e70070e3ed4d5f6d561767c483d879d2fec8b9c4e74824ac8bebe858f40f2ff1fd98c416cfc44ef1811f54dea18ac027c90ff1c3397a15574523394158f5cb712a91b9082ac5c2dc9baca5d0eaee56ff0fe543d74e67c6a42c351e712bd6cbc61a85f05682c453a4e249db49d45586df3003008faa93c1199d8c1856c104c95729efda706c4269e1117155b7d262d83ed5c3c83ab2808d2e15a2b760dd121caaf53a07e44bc27df785bda5998998d3a46db1fb870aa0936831236c3db4716e47f8fee930b5b7287edb795b6d4e5a019664581af327966c4e5c58b73c0bc506a49198fed41eb2c1ed7" \
    "f5ee7b1b548da8b5620c6fd7db4805703ed28ea376fae477ba2c94d0b2802a9edb8caf542c7d6f9cfa66004819d77f8c44b21d6bbe3ada703a6d919ef99435a932185a67b697f781d4376a6e7a3abca29ed32702dc38d59c61f9eb950790c662c139843b3a04c7cdb928b530489a441815deb44f181e5d63f679aa9c269d6630529836ba00eb67e971e0ea75c91e9d58717bcd3aba11f82dc394d79a9ce39b7babdc78cb4f75603bc408112747ef51c87a5178ab093b30628ef37979b289f0ac95ae505671c9392d7a48302d0834e8d2f709bf8a4ec48c6a203d9820b0b7ea29d8b6c844ac117a265a47516f5516e8ddb24aaabfd2d494ad411b3c77de97135" \
    "b3c9be77b4972ac8e2dae7bd575bddb5071bd4033da91d194b8356e66834ef2aa8906b5e48f1656ccbb24b747b2504895fd0a89ccb126ca854f3235d5e9070f7f869e3b67c825004acc520cad52f8b8131ed88d739eb907e9ccbb9aac56e8f340fc0c80ed3ac6326f28e082ef9edcb2329bcf5511e8731129f877a4d313192557b4f78c5c2f2275a3967521f5de25be5a3e98e88cd87b6fab9b0f5b3268c32d2a7308689eed61504ee0b9f2a75afa64f3cddb4eceb6faa9d97d2ac7b29c0e942304e71b99bcaa4cd8cc56fcee59842d65113f90bdca17481a6571f139f921e1a82e3bad37e625efaa23f147b025eaa019d26db5435bfbd3d51d8be0b0c5259c" \
    "23b8ac275eb2fcc42aac35dcd704554675d80dc547b2cdd2746b229c0049414efb6be490f8675450c131c7c2493feda5e2eac6c9b018b6ce5e18db2e0fcd9e7e980f88f0ec4e581dd7785201f01dd947c9d240c768d3de4efbec609dc79963b4626c435022af2db2d54b7ca2b2e842b4905624ca562b6cdab3ae59f10ff4b978c149bab782d2fe972170edac79e64f72a13f1ad7626a88faee286d33ce28c8531d6f982df4fef15525af4e272c61290b6254c9f874d65c371420456aee7bb7ccdea783ba607c2e7348d2471cb39ff7073d5fda3474b90d188d5f899e5636af6c6cb72367ae95de79f19f7f92f6e9e2ec9926f4944a59c626c1ade0d7eea0d7b" \
    "92f67223bc68e29ef8ae09f91dc861244dd73c01edfffade719d1f21e9e03583d9081253f90b2365e7a5b4e214fc0ae96730ce6dc19f2eae5fb95687a4ea55980f5cbd779f5482e4e29d9354b37dddf6bc2b90dd6e17ca6a8d0bfeaf4e6d00309c70fddf3db973845ff21fc167a26cc4a3244dd1320e309b601181f934eca7e606f13e2b52ce87dcd64fd4a8b01e39ebb2b73009bbc703a99f468b05f6fdbf10d53a08cc5ce83256dc033c7b0b45c7c4615101b769f6b62d9137744602f4d8498dd7d832dabb057ae7b8c1c8f7bd88f7458e1d9adaf1ca8fcc50c849f7766618a747470f5a9b73b16fdd0f1303fa1fecc5cafdf46d6ca358c71f118233070ad" \
    "6b7f4bfb23b2dffa2faec7ed99e6fdf2d78a41d84cfabf301181eca7f440b193c168cbcbc1ad72bc81f738b9d45a35931b48616ac40541c2115cc6d91b9172391696bc89d681b6a8923eedfde981900822ffd53db8de9913166a47589f09fac7f171e6dc6b18f4e7edecac60de45587a741866fa2f6d0f4aa71336c988929366db61106d875973a0176a3e8abd8dd31097f9dc49329aea904dbf5cd7df13833e5bce04e4322c7dfc991f6b248e404bf3150cffd1c84d740c8ed68228ab731376f92088e874795823fc72fad65748064a76b8973bf96ef3e7f5c06e64f49c8b363dbf652156284d3cc8cdb547228c4d3e40646b2ecde5b04807e5e934c27533a" \
    "8b0146338df22a47083976220f6f467f7fd7a44534d9af3584eaeba401ee652f1d98549d5184da5e6b737ca08dc689e9c3461ea528076043e5181ab2f0fd7323c407be19f079298c7eb17b5a8dad038566e8125d26f5f2a2398c782a99e3019af6e5ff13fb6dac43aa89eeba8fb147e4c3242bd7b203eae2face90858d2d95072ea97425c2d0b7268753433af441db8a7080c79f79dfcd889144d05e1b3bb1fae3c8d9c9f730eea78da415665bfd12e8e784722ebee7ff05a585d41ef49bccd8beda7c6b08fcc74935f2d1d737319272a0b5b800219b13ec9018083289dc5a430844f8a368c2c58e18d614d8168deeda248b05be228790aff961d9434b6bfea" \
    "c689ecaeda6f15dd89eb43b136a706c61fb8ae7b3322be9b249f9e3dbc9c90e87485e5fb4342714cb4023c103b377afbc9e1bea89e106a3a5fa46a44685822e663ffa439190d27ed8958b531372023d3c74d46a9caf9642fd82ee971dff15b2cba7f903006d61f08317714ddd36be8984284b04761e594c2b8c4838eca6f2501a28d11a7b0a741e5d3e7c2dcb71fb090610c624a08dde23b27efa061d0db67af43b28f68bf8775cc982e28f68a4465054d6fc67a69e736e14c36a8b49a3c097cc4757239dc7fa304a8d6adf3f5e3ee3d2d35429e2c0e78fd5021034dcf9af2b14e5f23e3af95b3d62a67b89a9f0233812ae44080f95790d75a3819f418fd0c9" \
    "508f7082edfd38d8a4667b3b431ac1c186c0627e676cc66b7930453731d6e3e721bc58ae1154119682660050952e6914c1a225f994e74e3e5230c179185f4708eae5111c6f8e640b7efd91661abba7a635dc150612757eda831d8ce15f9988a33ea2406a331cae8c1cc5b4e84e32fbfa65c6a6205aa7e6d4ae5f1e1c8206175a7f7c5cf4167f5facce36d153aa34d485d40a5fd4f7ef04c1168deb672a3571732fcbcd66843705f215c97d34a931dfdd030fa89054bb57046e227b7db2982591e219282df6c42fd086061f07d5aa6c74655f26ef0bbd6c3307a554bca5beb23b190ce3a708b73bec81754d49ba1f18c09d61414d8745a2c1959efd908e1995e" \
    "356ef868e1480c89aba8f7e76c0f04365fdce9e3851e499247a77dcb5e6294f0f0e69873fb4a1345f73bd292b74de9ab918ff844be62acdf038b88889186e5c32b1d37c3863a93dcf5fa6e3b4602a8d5e616c99d4ce88afa952d97786cf693be2d3e5cc04abf9135ed0b524cdfd7479aa89ae457f857ebcb45b63203b65aa6c8406f90d20f8217382796062b4b74d0e41d42d2db8857d73a5b4ee191365927cbaad85a619c2b2ccdeac4134252804a9a8f371a90c492572f1e1c2d8ab59c1daeb4a342d5ba61d9dc80bc00f7bba4bea444a044dd76ad7292d7499d56fbcb9059a6f5d09631cc254d2fa755b4508733ea85a6d82c6453314bcffcba5dd08d88b" \
    "3c8f98d0cc915180840ad9be0d7d2b15399715fe4572a9a424b5e0a08fc8a0ea661d4009f49e4baf6fbf559e2192c41c9ca28616c17dab860969717bd466b291abbb1b2b87be014fda7a81724de3ee9345ef4642e6c0c908bf7ce69e578d8e2f51cb629bd25b22d068ded5e0dedafb37a9efcf2911e682cacb52c86e958784020cd0bef1810020dfaf6edb4051028a784d26992fdf49593ac19d8f82faff44b8316d98c2f0477bdbf28d0a4740d51cc3a4262cddab83ccd716bfa472144f30b063e48866cc9b9443f6cbdb3c2add12a84351029913004e3e5f3bcf926e11e89928f7f67362671aa6009dc6b58b851c94bf59a30882596dceff84498a54c1dcc" \
    "0d4fa7b6f4e447f80c4956539cf678b275c8296a285e99c076c4baac084e97dc61c7e7fc10cbe2352a7253f3f72fefececf7e55ed9a5b697649d47bbb6af35c2743f68c0f1a3eb69a2cdfad4d22a5d7f96c9f59404c0956aa0cc134f17379e8530ff518aff34099c5ca2747d93b06b745d8882940f78dd40129845ef93ae7a2d7b4ecbe3a246e5d73f39e976a489c1d2287ab3e764953622a24b052492db73c33f76fe5142a0262135d980486b7d06a1dee9b11469df4a17382c7d747c872f4d63bd115e470b758326cb617a5254e2e9691ba3a3881ebe27bc82d26ab97a56d6cf6c2d92194f7a04f858b594bfd5ffb3b059b21c28193d5a16962f8bb17c916" \
    "36bca79742034dcac94c6a41f1cc902069bea0608b0996db92eb0ba61cd5588fe1f211e8cc5824483e25d55a2d0f896eb1218c6ef8a66f64bec179b7373cce2aed3b743626e005992ca67f1a5432a6169fd291b571d4881193915fb490cab477c6fd6117f8577c4e0352a9fb0dd270b8844662ccad107b629fbf0026c01b8616edbc4b06a70af2c7509ef884c06b63d50d01722cf0e6a3c851cf1d763b8bcd58fffc947ab99703a5a30fed30026a19fca878424ef3c3abc358260a3b69b7e4ee4c32ffecb66829696909fa955a5aed8fd52f45bb0c33fdd3f17858dee11c87277103cfe5141ace731131a32d2eba691f21ab1ee9d0c4148adc1a7be928160e9" \
    "4fcc3a6fc591b7d534a0b695ff605071afc501063b7d08a4876a105d2a550f5c74e16f79b0bd6c0aa61ebdfb646d76213e3c2dcb147f5b9ad3f906933ef49d73ef352442982f902b8f77758b8a78de48a7687c64af7b04d29b56d28857c6d2d5c7b2a0f5084eeee3f892276ef8eb518ff03038fa94d7c9f3e669bc63fc33762b043f2db885824dd7e8571acb362c979e237ba7b44cfd73a6bd1a0b4db6a3501cafc311b3993374b267ae98cbcda5781c473313bb5e53ca922751096d0c7e2951ce289510cbc92c1a7d7fe79644bcbcb1653fc236524395602cf6fcec862cc9716c5501f4a3ac3db733b2505323db2a068487fd4eb1339eb7d4f12df1ac15f82" \
    "58e329d89aa456f33902f1b2bf3698cc3acf30b2b018dab40282ae4a507a27e153ea7b0f767fa8a339cde90453acea890e56b36f4cdb885a22f89692f1e3922e8839c84666334556260a8f7ca8371461338d7c4d29a1cf486f1f703b87944ad4766f95ffd245c9965e37397e153bc30f7ac1ffeecf221bf94775afb68a129e8d9eda68ae434d81ee72e29b9b334162de24a2b2c6b5c2fb073c89c99661d529847228b4d441b12ac8e47b0a567ade7047d19e3967661ae8dcceca325db752588380d91ef455f700b0238f2a32647987e6f2130833687061f46ec59e7ee320c7f55b59eba0e8a5c02ec09d5fb18888f63606af83dd2599f2e8acfa427c8db6e44" \
    "46229bf4c8243d5bf4c043f464fa357bfafd250a735ce2823f9d6e2c90f8b2a0b25c71e69ab37bdcc16723d73325f28de2e19d33411a35e20e5f9e3f6f12425b416c06d8adc17e4efc055cecac902f63c31e4aff631a01179f1c1ca88db0853d9c59441228d5ad784ca3d87bf8c352c343bd12b802e4afea99dcd0af115ae30e6b2b12db347872245a487ecc3e46c5760ac5dfa44501a520a5a7a29c2498c49555ea577df9303418cefc3627a7a2ee44c13e980d55f84d846a867ab6edf3909b039ffd3e9e885c1d4fc7e8d35b5e37f41030253959510edd9180404695f2afe81d52eb674c0550fb85b27c19810207509ea46e717a954ff2c19edc94431e8a4" \
    "44a09093f2a31797a19c4db414116c51e14a15afce04b7a8ca3e736e820fd877732ce3f1061933f62b306eb93c423db271930d324b2fbf673de63368a54190f487ea8752018b30b7afa7e955632b1b0335658c12f192d2b6f1b1ac5c106fa8b80d6a093b9781a438b9736c2d4b346ac0a73210a663c6a81480215c9d75e2661e7e1bc8121a94f515d313658536d6c377317939711443960c53a5b2b128527fb45480627a0d2da9bb87184411c8baab937eab75078582330b06cf4d4bba385bf62b2866e801b448b64ff2a637733889a1e96941de2a1af59cf3fe9ab19dfc61706c8433c07ad1487288230a8ab8e8f42f0c032e799466543eb5c41977662746a" \
    "f832457b7fb0d2f9cea39cf602c3461a75129a94e370cd56cb6a04821854161f019794112e4b07481c097837c2fa36887534d30e094770fb39123a5348dc35a0e9a039e85da73adcdb5ccc52345de5f5b7cee53b52f2d598fbfcecf24e22585478f43be653ecf31dd2469e2fa011ddca0487d905089a8497dacf2246724f07a3753ca2f55a41ba73cb6df8b64e41a66d2407b6537166065e9e34e239fc8bcbf5aa1f76fcb8ce18468c79e1cf8513c648dff7840cd77fe2570fd236b233fd2ab2dd46c0e2b6bc94fedf1362628fafc7c1fdff4c1a800ca0e8f452259a61ceae42d75888919c33b7038ae38157b23e314245c61564b536c97b175bb7d7cc25df0" \
    "e60fed4f0b25a07bd5590489637e88a3280f5e7d2bd25e4773e96f552bc2b447c40e0aee73f5a0e950ac3bf0766d45cf97633ca4ce200794432aae6f37b0865f53ea51d5e8d5b54f16f23ed93862b2effef29c7ba6af0104abb4093a350e3cae223f52a3de284603a4e59da20e11489abb37fe5049e1c32f0a000024882e4fca9b77adb6c87fdbad96d0c8e97bdb8f46789dc2d13c6ad66a0ab913dcb5a3582b4c2d93ad4c4efea3494e512e1633ff79b3be8a5cd2aca35c2a29c4c1520fbe4690cbd4f5be08278b58d8b6de41bd01aad8f4c571b119c26bc4ec8350d1c61ab325ccc21ea25ddedc31fa8a78a2c93e6064eb04be6c54ac1f777be029a958c5e" \
    "767caeb86ad929d1c511e1c9bae0b1e20e40bb88148cfd8edbe526bba6d5a7859c320c1cc1458daa252ce0d95c7d52972d2c16168eafdd16d15fa7661822d8a80e478e56d9b132024a384de2574c9d8bccdb69fd3d7511e03fafe90dd8c547503383db6c98653f609cfdcfe99595bb4851165b450828c2748e9b95b7cd061e0473ad9c69e8a8dd4d83420ff8fda0d45626a394f7d60e175b27ec536de12c824d368f7852b0c4345067d1b51677b40f3bb14abd1b9171391c7069ca36fb819db2e4ef1831d8ff6bf1b070684ceb1a94815cd57eb720974f3fd3dca31a034b97bbe596230d47a2abb8c6e8d0a1411b8caf8e0a7ed56bc9824db70b8521e2d398f" \
    "0a24c42efe7f41b2e1200961d61fd1f4eaeb3667c5a4efacd84c019547e61c7da81d81dde9f3fe4dafa8262c8340874e52696ddb5d570de47a1c107bac03c4c00eb045be257c92d44e734dbaba086b4fc5d7c8c87c475564378d6f65b90ae50ea4996a503f7dc1ff542e0aacd8ebd061cbb2c1afa0fa68c4a70c98e40d7fdfb210157a24a68bee274714c7736e7f693cba87030169e4ba5e3f16178707b72742c7d0ffbbe90b79d49de41e9ef917982948c0e76e459accc9763655cf36655e49323865768581178fdef86a8ff768efcfccfcf936b291027ed2f9ee1d27eee72df5d835f4ea8129c170ee55d6e7d7d298dd97b30b3f4c1de6dbbd4b014ad8447" \
    "9792d0bb7a6904311fa224b0458d8d30ce13daf4c5a4051a9f70ce71c1da618a43293312f4812d5e9e130c488b90083a47e3b388a81f25030cb656cbe2edcb646c8c750cc2dad64c1bc865ce486d346e81b2d093644f68c03bf632667ecd0bfd99225e52ee5b46231e2bf7e9840c5af503e9f7be021a187ab4962beb9d64697c5253b58c80ebc70a2fa389424855c1f655eef1b1896a7b580000090247992c091f8744627e749f29d798e5809b30b39a002b86130126db83a69a945285549ece8926d17af2dd17a99d72d14c868576098b067d8d73367e222ece94845e7d05f01798257fe30e77b20a9a164e103c536a7ee9a0c6e682ad5e2103d03fdbfdaa9" \
    "a524608175aee076ba5767c2d413d92e5623bb56762f1af5f06a0112c03bad5f2c09641ea5e670ffdf66fca9221707ba4be648517ef6dce4c650f1ff3de9dce20ebf19aa1f760d69085eeca24b9bd56cc1accd87f96de504dc7b7c23b748edc4d5bc0d9e42dc2a54adb59428c100d6a88fedb76465e2a7e8cb200c2acce7648a19669c75a0973c4567f19fb712e4600fef3f92615503aa02eb152e6eff33b5b4326562cac925c7bdaf997bd7c1c526056808eb19472f6fe5e4915f7acebc75a5c93edd082d16512ffd23a4f55e117d2b92e02e06ace46df4204b1be8abf00901363987a82cc77d0ec91697ba3857f9e4f84bd79406c138d02698f003276d044" \
    "9120bef4578d78fecabe8e070e11710b3f0a2744bd52434ec70015884c181ebdfd51c604a71c52e4c0e110bc408cd462b248a80b8a8ac06bb952ac1d7faed144807f1a731b7febcaf7835762defe92eccfc7a9944e1c702cffe6bc86733ed321423121085ac02df8962bcbc1937092eebf0e90a8b20e3dd8c244ae8cd1d30b9c6aef438d0de7feb5c662d4a004e8bcb3a9a5c70f5e6a0eb929f5e8f7417261fd2142e8c8dbfa484bafafdac9dc71f882b615b491f938ca155d80d48f6a25bd8b8eb078836d03f200789a4502c1102ea20de5c1f62b7e5b35856dd91bf5f3078fdac35b846a09e41d4aab7d145ccf465cd89d55059e46a861ca455e6589e5275" \
    "12c03fa947b1506e94c6beac754b528f83cc6d787f79799e0548fcd33cf010619adf7bb7a482e40aea761f4e251cabdbe63e7b145e17a16fc4ad38d4e6f518a2f84270700785c7ab28216042ffd17ebf575884a0402f507fbd49a067e10dd9cdadb1b47ecb3a79c3f06108074fda39be799310a8f021354261c6aa08a5aab2564d75ce107a3188e9b5ad9d27afc77b6daf86b59ad8ad9e6c547cec33cf7c60b13a2713f19eeb6380ea8f96009a0992217babd9f254251a320804bd75a8c33383064e2c7ea3c8a82e215f694e99113c9e606b044c0d182747eed6b44adc4fb92024438e341369a555dcb5ad5e178ed918e04cbb046e0744129b6b572fd442703" \
    "d36bfafae783f097c9f2ac8abafd2d6459de964c7f1630f36704b1ca12b7bf72e901b073a5cc94326cb1751d3cc7dd298db9997e321cbd7081ffe8b2b3c3c9c68e2de2b841b98c0c8f313cf52f7f04c873c05daf299923a2bfcee193aa104fe90717193083f1e20f799a897a5bccab28531869482a366b70689a24d6bd4758c29fe8dc43351d9e227413e5148857d93375ec45affe9b9cc1c68a3ae1b510ed399dc8b4591de4c62cc6c4d62b7dc896d020627a4e6d6fbe7f1fc7aa1e5912153648de28da05ef6417b8d6e62703c6eae79ea28f8c3e5ada91bc78fcf373f6d8a1ea53c02eb3e67fca92719d70e2f9de6135d50cd03b06f6dfe5c6b9cac9633e6" \
    "2c94e04beef6f202d9cbc826ee20a79242e237a842a181d51e1d9680a250250622df87df083354e281ee01d8acaa1c419d1b35f0fd43b54cffad8911b4d7b15876079b22d35de11a35f05f62a6465c52865ae46d90115a54176ebbd65097595baa9f82bdecf137186a85196b876ff863a343bb44a784e178f9e3c72502399d9e44f9d7169177b77b941ef849ac9160f35848333ca038fb2a1baf03b44618ee8eb9b920b38d6bf2a247205483a255366039eae4ac168807f5f12329da98dfccbb9d5fc81b1d38693b083bc6bfe525e958acae3829770c885b2ed2822e76d8d883445065c3ed879b843bb3b745017dea4b44f4a61b4e30fcd8095fa5166cae729" \
    "4632d52346ab40a3c663abeb973d7c9967770c718089ff5db350d1b28e6bb2b5d6e6945e3115825c22c333583a8ddf7e8d88513a642a3e3f3167d5cec81a9735cba7699666dee7e93d23fc44a3ccaf5a0dcb4043c68d747be4222d2c7a9d3db00fbe7c514fce195401cb2d3739c59636cf8802140f7b4a17b2c802550ebd4e2e8973f61a53adbda55502efb7643f3a19bb07be35a8bc671d85a37bcfea426fb8210dff76da427ee220126a4e8c01430bb98f9d2ff718759444f9c12478f44a54bfd6beef4c5601154c41c58319d45a15b169c78866571985d713fbdb1e9b870d4b145c0c12b1f145c0d829de7380273d8bde63cb5c40fdf72539527d46fecee" \
    "8ad100155921bf47b641ebde803cd518d2f349a7d419cc9f218b2ee9157e6c5efce12d353355cb2be205daa282f83810d85b393287c33257f97c8f69fb91b17299461fd8d633bd516dcdb172760695ec476a5775377cdb7a48bc19230d3656a9ee847a58c8582028b80e22d6bff4891bae8506d8799322a6bdae6eccb0f8c6757b30af4d601f7e326f4b8137e72e8c1f7c4fe9e4b4a2924dc6d7f29f8d457b55bdbf311f5416320ee20a5f2e823119784f3f53127f27c4dfe2cd4743f8b8ffcb24a4a2471ab8d61ecedf3f22f788bba685c7d4fa3f9f14fd9ff2cf3299afce665e65757d0a93f4d2641e83adddb1dd4abe6e02048c851cf75cfd1ce3d6a6619" \
    "7b9961d09ca23f8ca606cef379b3918a567b64cb9dc56378db82092e0363953dfc49b2b75cfe56c77422eb448c68ad866f0253792b59f1ef12021d3b04ed51fbf1e0903599244ca6967f88569d623a700162f35178ecc1df2235551cc77161fb61454472da7ee9d01603ec513408ffef11858d7c0ee79dee1405f8fad5558ee454601695a773f5eefb98615cdac4c6aca952682175b04bc4ef5950fcb403a05ed2194dc6886b37a74e252d9f15fd554fd0b1ce6933b1930abb18a34beee15f13e458332f06ce78a416919943701c757f8f8a057cd2513f68802c3a0e0b5992a891050ef5a805808c5bc6ed707087eee4edc55681daf71585477c5d6e91d203c" \
    "8e2082743f776170826ab714d9fa78827f24b09a0d10ddf0a17f053930ab47819dd49c63f7a8a05c07e286d0384e40bf0a602660341fa639ef97066a4fd66ba438cb13311b9a9115b6b2528b9a7a73ee612d3b5cfb1266aeaf4e4dcc9f35291eff726b5e23c3c0582f58aeb989156eab23da63d2faaf9bb961034fe2c73dfc4c5259195da8ca9a7dc253ffec8c95bd7fc2f644749b3db2049554914f205751d6c1edb1c20305ac012022da970d71ccd6bf1f31b4554345fabcc096646317c628deaea8fddb0b517cb943a34b9440394a78a3d014c156c41657c5d3b4e805c5ccf92a83938952476b0e44fe6ca9776f359022941867feb8e1f6e2ddd32797ed3" \
    "db1dfc615a650ea368f95508cc58dfb429629e221a19190e80"
#endif // LIBBITCOIN_SYSTEM_TEST_HASH_HASH_HPP

// test helper for acccumulated pairs.
template <typename Algorithm>
typename accumulator<Algorithm>::digest_t accumulated(
    const data_slice& left, const data_slice& right) NOEXCEPT
{
    accumulator<Algorithm> accumulator{};
    accumulator.write(left.size(), left.data());
    accumulator.write(right.size(), right.data());
    return accumulator.flush();
}

// constexpr test helper for block construction from two halves.
template <typename Algorithm>
constexpr auto block(size_t a, size_t b) noexcept
{
    constexpr auto half = array_count<typename Algorithm::half_t>;
    typename Algorithm::block_t block{};
    block.at(zero) = narrow_cast<uint8_t>(a);
    block.at(half) = narrow_cast<uint8_t>(b);
    return block;
};

// constexpr helper for merkle_hash with two hashes.
template <typename Algorithm, size_t A, size_t B>
constexpr auto merkle_hash(const auto& expected) noexcept
{
    typename Algorithm::digests_t digests
    {
        { narrow_cast<uint8_t>(A) },
        { narrow_cast<uint8_t>(B) }
    };

    Algorithm::merkle_hash(digests);
    return is_one(digests.size()) && (digests.front() == expected);
};

// constexpr test helper for merkle_hash with four hashes.
template <typename Algorithm, size_t A, size_t B, size_t C, size_t D>
constexpr auto merkle_hash(const auto& expected1, const auto& expected2) noexcept
{
    typename Algorithm::digests_t digests
    {
        { narrow_cast<uint8_t>(A) },
        { narrow_cast<uint8_t>(B) },
        { narrow_cast<uint8_t>(C) },
        { narrow_cast<uint8_t>(D) }
    };

    const auto result = Algorithm::merkle_hash(digests);

    return (result.size() == two)
        && (result.front() == expected1)
        && (result.back() == expected2)
        && (digests.size() == two)
        && (digests.front() == expected1)
        && (digests.back() == expected2);
};

// rmd
// ============================================================================

// test vectors
// homes.esat.kuleuven.be/~bosselae/ripemd160.html

const auto rmd_1 = to_chunk("");
const auto rmd_2 = to_chunk("a");
const auto rmd_3 = to_chunk("abc");
const auto rmd_4 = to_chunk("message digest");
const auto rmd_5 = to_chunk("abcdefghijklmnopqrstuvwxyz");
const auto rmd_6 = to_chunk("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
const auto rmd_7 = to_chunk("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
const auto rmd_8 = to_chunk("12345678901234567890123456789012345678901234567890123456789012345678901234567890");
const auto rmd_9 = data_chunk(1'000'000, to_byte('a'));
constexpr auto rmd_test_count = 9;

// rmd128_tests
// ----------------------------------------------------------------------------

struct rmd128_test
{
    const data_chunk& data;
    const data_array<128/8> expected;
};

const std_array<rmd128_test, rmd_test_count> rmd128_tests
{
    rmd128_test
    { rmd_1, base16_array("cdf26213a150dc3ecb610f18f6b38b46") },
    { rmd_2, base16_array("86be7afa339d0fc7cfc785e72f578d33") },
    { rmd_3, base16_array("c14a12199c66e4ba84636b0f69144c77") },
    { rmd_4, base16_array("9e327b3d6e523062afc1132d7df9d1b8") },
    { rmd_5, base16_array("fd2aa607f71dc8f510714922b371834e") },
    { rmd_6, base16_array("a1aa0689d0fafa2ddc22e88b49133a06") },
    { rmd_7, base16_array("d1e959eb179c911faea4624c60c5c702") },
    { rmd_8, base16_array("3f45ef194732c2dbb2c4a2c769795fa3") },
    { rmd_9, base16_array("4a7f5723f954eba1216c9d8f6320431f") }
};

// rmd160_tests
// ----------------------------------------------------------------------------

struct rmd160_test
{
    const data_chunk& data;
    const data_array<160/8> expected;
};

const std_array<rmd160_test, rmd_test_count> rmd160_tests
{
    rmd160_test
    { rmd_1, base16_array("9c1185a5c5e9fc54612808977ee8f548b2258d31") },
    { rmd_2, base16_array("0bdc9d2d256b3ee9daae347be6f4dc835a467ffe") },
    { rmd_3, base16_array("8eb208f7e05d987a9b044a8e98c6b087f15a0bfc") },
    { rmd_4, base16_array("5d0689ef49d2fae572b881b123a85ffa21595f36") },
    { rmd_5, base16_array("f71c27109c692c1b56bbdceb5b9d2865b3708dbc") },
    { rmd_6, base16_array("12a053384a9c0c88e405a06c27dcf49ada62eb2b") },
    { rmd_7, base16_array("b0e20b6e3116640286ed3a87a5713079b21f5189") },
    { rmd_8, base16_array("9b752e45573d4b39f4dbd3323cab82bf63326bfb") },
    { rmd_9, base16_array("52783243c1697bdbe16d37f97f68f08325dc1528") }
};

// sha
// ============================================================================

// test vectors
// www.di-mgt.com.au/sha_testvectors.html

const auto sha_1 = to_chunk("abc");
const auto sha_2 = to_chunk("");
const auto sha_3 = to_chunk("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
const auto sha_4 = to_chunk("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");
const auto sha_5 = data_chunk(1'000'000_size, to_byte('a'));

#if !defined(HAVE_SLOW_TESTS)
    constexpr auto sha_test_count = 5;
#else
    #define BIG_SHA_TEST
    constexpr auto sha_test_count = 6;

    // requires > uint64_t size_t.
    constexpr auto alpha_size = 64_size;
    constexpr auto alpha_count = 16'777'216_size;
    constexpr auto long_alpha_size = alpha_size * alpha_count;
    const auto alpha2 = to_array<alpha_size>("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno");
    const std_vector<long_hash> long_alpha(alpha_count, alpha2);
    const auto long_alpha_data = pointer_cast<const uint8_t>(long_alpha.front().data());
    const auto sha_6 = to_chunk(unsafe_array_cast<uint8_t, long_alpha_size>(long_alpha_data));
#endif // !HAVE_SLOW_TESTS

// sha160_tests
// ----------------------------------------------------------------------------

struct sha160_test
{
    const data_chunk& data;
    const data_array<160/8> expected;
};

const std_array<sha160_test, sha_test_count> sha160_tests
{
    sha160_test
    { sha_1, base16_array("a9993e364706816aba3e25717850c26c9cd0d89d") },
    { sha_2, base16_array("da39a3ee5e6b4b0d3255bfef95601890afd80709") },
    { sha_3, base16_array("84983e441c3bd26ebaae4aa1f95129e5e54670f1") },
    { sha_4, base16_array("a49b2446a02c645bf419f995b67091253a04a259") },
    { sha_5, base16_array("34aa973cd4c4daa4f61eeb2bdbad27316534016f") }
#if defined(BIG_SHA_TEST)
   ,{ sha_6, base16_array("7789f0c9ef7bfc40d93311143dfbe69e2017f592") }
#endif
};

// sha256_256_tests
// ----------------------------------------------------------------------------

struct sha256_256_test
{
    const data_chunk& data;
    const data_array<256/8> expected;
};

const std_array<sha256_256_test, sha_test_count> sha256_256_tests
{
    sha256_256_test
    { sha_1, base16_array("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad") },
    { sha_2, base16_array("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") },
    { sha_3, base16_array("248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1") },
    { sha_4, base16_array("cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1") },
    { sha_5, base16_array("cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0") }
#if defined(BIG_SHA_TEST)
   ,{ sha_6, base16_array("50e72a0e26442fe2552dc3938ac58658228c0cbfb1d2ca872ae435266fcd055e") }
#endif
};

// sha256_224_tests
// ----------------------------------------------------------------------------

struct sha256_224_test
{
    const data_chunk& data;
    const data_array<224/8> expected;
};

const std_array<sha256_224_test, sha_test_count> sha256_224_tests
{
    sha256_224_test
    { sha_1, base16_array("23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7") },
    { sha_2, base16_array("d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f") },
    { sha_3, base16_array("75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525") },
    { sha_4, base16_array("c97ca9a559850ce97a04a96def6d99a9e0e0e2ab14e6b8df265fc0b3") },
    { sha_5, base16_array("20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67") }
#if defined(BIG_SHA_TEST)
   ,{ sha_6, base16_array("b5989713ca4fe47a009f8621980b34e6d63ed3063b2a0a2c867d8a85") }
#endif
};

// sha512_512_tests
// ----------------------------------------------------------------------------

struct sha512_512_test
{
    const data_chunk& data;
    const data_array<512/8> expected;
};

const std_array<sha512_512_test, sha_test_count> sha512_512_tests
{
    sha512_512_test
    { sha_1, base16_array("ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f") },
    { sha_2, base16_array("cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e") },
    { sha_3, base16_array("204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445") },
    { sha_4, base16_array("8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909") },
    { sha_5, base16_array("e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b") }
#if defined(BIG_SHA_TEST)
   ,{ sha_6, base16_array("b47c933421ea2db149ad6e10fce6c7f93d0752380180ffd7f4629a712134831d77be6091b819ed352c2967a2e2d4fa5050723c9630691f1a05a7281dbe6c1086") }
#endif
};

// sha512_384_tests
// ----------------------------------------------------------------------------

struct sha512_384_test
{
    const data_chunk& data;
    const data_array<384/8> expected;
};

const std_array<sha512_384_test, sha_test_count> sha512_384_tests
{
    sha512_384_test
    { sha_1, base16_array("cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7") },
    { sha_2, base16_array("38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b") },
    { sha_3, base16_array("3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b") },
    { sha_4, base16_array("09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039") },
    { sha_5, base16_array("9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985") }
#if defined(BIG_SHA_TEST)
   ,{ sha_6, base16_array("5441235cc0235341ed806a64fb354742b5e5c02a3c5cb71b5f63fb793458d8fdae599c8cd8884943c04f11b31b89f023") }
#endif
};

// sha512_256_tests
// ----------------------------------------------------------------------------
// FIPS 180-4 adds two algorithms: SHA-512/224 and SHA-512/256.
// The above vectors have not been updated for FIPS 180-4, so use these:
// csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Secure-Hashing

const auto nist_256_0 = base16_chunk("");
const auto nist_256_1 = base16_chunk("fa");
const auto nist_256_8 = base16_chunk("b4e2e8501f54be91");
const auto nist_256_a = base16_chunk("97e003903bb971a523ce0c82bda5d6733c76b90deb307559c1bddd35368743f6563b315214cd5a7ee0bccf937c9776360bc0b9786b707bfbc4fb50576155edbbbfd5ddd8e43a76faf2ec0c78fc84644f188d6b0ab68c28e5303ff031a223d9fafb3871e85408af6381e629fae67488068c68398a758f665e2c12258d9ff8effb31ec534b0c40ebffb43390e1e26fcaa28fd68ac24f7e1cafe0fa573103dc17058a77edc9b3ea1418b45aa7f5977e126d4861c778ed6332217581eee674d739622e63a529f10c11f4a9e3d8feaea848ade0905675f6458ffa132f52749af23d584438e5");
const auto nist_256_b = base16_chunk("55bd3d3fa75ce4046b12fe44420bd7ab73838a7a8dddc5374eefcca3c4a1c1edb2b6222535e993f3a73cde89c48d38d60b6ac6fd67265f050f2c94d2ab94ed54b8f476fe2d797a7a5f368f9b22bbd29331ea7466d006769eaf0db041124818002f2041b1d73322ff59a71960a4be3048abab9e9d0ea5916af6392ad740e4c959dfe18c267b4012ec5e3885c291bed75f42564b89692a38d1ac590a7e7f9189c78fe05e4561c7d2a73691daa833e2513ebe9384142bbdf33b9814561d1577dfb209c5bff6d1f1eb9aa95920f9d053244fe70950259a884b108313189b4bbd53821337b72112e6e42b7f385f9fb139dbf88561b7a500b0c7b835fe57e2698c6d9f76de4fae6dcd45c47fd8a0811ebbfba35f43c17aa360f09c767c1cd9b70bb671fa638e852ace97cc73deea875e010eb73e55778dccbe4c220e356e687d63b561666e7d8e911361ab21f54699bb349c9cea42e0c6c2f265b3c4d2557702bbf2d584a622b2e9c12bc851c3bb9f7b7c2bb92bb0040dcf25c3b861fbd9ee8f3cf6361ab487d77c037e8dcdf05181e7004578c948ec4b397fec97ae5703b56c0d48edf13fb4e690ffe0615c25102747e971408bb19f6649276aba708fdab5e1587160d1f0afc86edddcacc50a017ae35e387a3a9325484746c587724a66d43642f7f9816f82635ec6f7d7d1462b600288208c9e9887d77b0383687b31b0fbb2f5641fcb6335a1a7e2bb48488297c2ee8fb3df7f66ccfd2c872ec452ecbf139e993f397575ce699358af68f2654b89ed9a79dba5a5fca1a4f94d02c0229c02425511b1484c57a268515b9f9698519b48d1f9e8d8fe20ab2982698c8d7b4db2e65261ee0c91d7366ff44856fec2b1e2475dbb6fdf183f02044a09c981a1dc09d2b8b75889eb570cf06afdf3f08c7145316647d6839d61907d78b521633950f14dae9b578603de0c33da02e0359d9bab501326878c328e3cdb35f6fcfdeeb251a15c9653cd80741e7f6de083959f36feea8ddfe8c281cfee68a852c21565091014eb2fb4240b212a1e4a1e46d7374b2548fcfa63ec322b8e6afa53db74495d18ef83efe2544cee18569b4490c50fe108b287ff5fd4edab052a5281b0e240b7507a4b5d4625eae2d07085dbc825cf008f6f56774440595639f0d963a727f21ea0fc6c01465e8e063bb3326a58c01fb0a2c992ea79f91e341304b681290a099af0bf0e634bc9df603f69ca79a75ea5fa290663de68c7e54d7bad12639f542a332809570cbe2c86fbc5d874901dc70ce50c6ff0dd787156aa5a3415926fcdfff23123728305502adcb64a593822c2fa7a334c626e11c1185296e1e695033d30def15585508afd740df805a1f81e1818c086e5e01a9b7dd44d19fcaef4c16c65ff51e6b9fcb3fa0b957552735979910dbfee8193677e6e31a4c9cd94381322455e3920350eea11997c1378f7e29bf5817f516aa3df235cd85e909cc1e8602678029249220e9608c3cabcc1571bed0c1e0999e6370af00f708355b05d8c0f41a7f442aaa7841ea833885773b88cd59e8964ac3e776f4e4ea21c00528fac8a3b7a3a338bedf9ecb991beccd745bebc726d9874ba8c96a6e2162f78ca7fd138dc98de4b341bf567038472033523380b5170aed7a19e075e9473c7a760568281ebaae774ec5afef74db5aee3d57d8228033aadbf3dd44be02a61e9745c3c48cd32575e95fcd29e0461cc7956fe79257d50749d13d457e9926c8a9fc70558aa8477484a96acaa5cf60570dc44f93fa87000c686bbaf4f69de2493f088a4d3300e8324b35e440bc0360249dd930ff8936bdad7719e16e3542b1827e59f81d462d41e94a2d70c1c532a2000872c85cc6fd5a75065a6503b30e011ec84f5e484c93c0f401de84c069c3b263ddff7a6e2c2162fd86bbaa7808867d78ad770150becaf20cf2f794bf024d1dea7efdcb96317963a188ac261dae12732aae6f95b90539617eadd73520371550ee7bec40576f3bc90b8caa7c770c588eaf4b779003b8757bd3831bca9660d2d7fa55495d344e0f2f85f334f216bbbf2c60f55d64a350f5cda62323d984280c3f988ba396bf565a03cb5cea3b7f24ccd90a4c5fa82a6730b360fe8de67bf507e4438f79615b00b2c2264a28bd02efe810e5a10cbefb63cce98e85c885d0407c5275e1396199d58ff7311b7f0b6475c7609da3f33db8bf10cca949521c33a2c026ba21720bee5d681f66616b8af64eb1548cb5a198c501a2c92bc9b92e188489cd8ab0a1b4eb00d1a750bc6cd04ad35c495d667644b2b4098b90877c4ff17e2fb3622f4710f258433b6a8cf15fd4bc1ecb6a370fe6044eab7071f309e650f82874daedd094a6dc33283e43a7ae16617f674d97cce13c4a0f143aace075b97b1a8e5f8cecb46af5281a2670ee3fa25c048972094bcacd3eaae37505ae928d7f5c6c5a7ce9f4d14ba86dbda53378eb1434ce722bfb072985156a9badb2b15f8d949b664e66da5c482abf8e51260e63228692c840592ae3c5c51629059b56a22e29980d71d1d97e63257bf2f52454acff8062df16e4aa9e694082a79dd6f6f7c9a1eeba77b976ba352f1fa611bce01b03a8db30f03c1a8bf7fe1c81d6d416b2f8840bf7d08c369226be36f2275e355fe76658686cbddf6efa74506251413a8623468c300cd8ad98c0494e71b696c8ce134f66effce87da9d949daa39d7cd6c3e27fcc0d9d1d20208a66c29f4fe51ef80fda8332215a89bf2cc4f7d00c05700ebe8667eaf1c852dbfd8d3ff543d7ac60458e39c96a7268215d9c54723d699ac90ff0cc52bb789a2d822312fe32cd05994ce0f72048debd72e4365d049217bb756f5585df5a9c8a97c0cee824ad639ef59e6947d13cddde2679099df1baae66b6451b00db4fa288ad31f72c031409ed27b28da856c71e6eae64ac83e4178c00ee39b7e9e10b3938c04e226b13f74e848211c4a52b680ed39d3f859b36293f3e9fa5c29d9b3dbf0f838de701c1d79fd9a734b4aab9a03d9155723b60726046544d21a1983427a27169699b9cb7357c7109a3c435ac00194c79a52460237d200679260b66768991f2e479d6a84e8162df1be779e25cf820596c30d716b3a05aa9963b3684ccb3ec2887272e91024bf16870685c1d5708f14ccfadd9f0cdaa64d236d9d97f91374f76c409ea037d05a6c189bed16324a2ea9b0694838abbdbcd04dd7a5ab37e940a621d9abf5c094ed16eda5370303066aac8935d8a4118b4f1b5fca540ccef5acb7f0642152751782fc4e4becf2124b4805a089154c06ed6816a16d302286debf132109861e1c02200682b5934a25c2d29d3d8b8696518a0da95be9c356274c81a0fcf264c17efcd01cd30cb47305120f5aa763b3ebbc0c49bcd465950e78e9fb47c84442a363ae99268778d7d57ae40725283a24b40d182137550a2cb3425a34f1cf2aa92c93bf830ce72085d84be0c3e7063862570d599f0226ff12ae4d4a348457ca20c4d5d896b63b2d45e442ad4a868a84f43e8474ca058f6dcf65615f04eaa94c2fd3f2a1db0ccbc6a06125f4a4ecfc4762cf3a14aa29d87ce9424641ab090dd95ec1b3c159f7de141db7bd5cdaffa4a83574f6df48544853eaacc39931cbca9936f6dde1185dbe3f444ed28ef3a9c9d0f494827dab6f281b5a0ba20f9f162ab33eda3ba82128b16e9d8e2c31f7d0b5e62796a497db63c0fbbfc6a94afcd4734ffed594bf7b3e00c9b1e092eeef5eae1356e425d5e116581ca347a1f350ecee97ff50afcd2e89f37907aacd6de23afd7f0ae5ccdec47238a68df551b1a446e3b1c8b1557b43efd1a62755a655d84cea51ca01635b8c5ea8c00638832dffca9ac5e2624e71c15ae4779a4ae24fd97cbcb21fa0b0f342c1ef929578fd0f69605afcd3c96256b0b17215e7f04c02eeb2bdc9902a7d4fed855645c21d88feeaf06d7d255059d319dcc4a896aeab171ed633bfa507901695912501158feca28b6219715f5efa8f03c2225730eec63572d067bbe6a0b1f142cda4ed1737f1a4539ea7000a5a0e33764dd34a3c176605f088a1e6dc5baa88fd211a324f7b5fac4b8c5f51adae5d667a6421aa4291532ea2e729670ea14282cd75d1f745c4fd617915888dd0c1afd118ef529fcac3555990d3466704db4088bbb10f65827b946ce71f6bdbfcfbcc1b57d7af505d17342ec135410e476f6d41cebd1da48d06ec749d935164b7c47ced400280e682f4b7543df662835ec791560e8143dbeecfcd22a15a80508c8486efd9590d88c2c2a8740cfcf1efd149746e83e6c8332e3cff1efd5a41c600a3b3c82cc49d5fa4eacd3537313679295fdd3236d2f6d3d4b7490fb97ddbee9d89cb21412c7a93b0d2ee40c47c794aed7095492e2e13e368a7759edbaa98f1ea9f96a11e77ea4b6ee3d53cbec40189a5e3655d73e3688d737449726dc9bef76f4bdbf1cd8f36af678549d22af3175fda2213130ed83df77c858e3476c19627b5f664b8565aa6e8222111aa12f003f41294671506f4da490b440b8bff7c68aa4309f79fbfc2811e271df66b7da30d6fd8a12b0b632186aca8188a200fe17ca8a1ea5d4e12ae1178ffe3c0be74f47df9b1b1259c2e468a48dc69d19aaed8194858035e6c57059c1f31d9374afecb9ab9272c1e716e4a2e442ea0aaa2e44988b2efbbc1a194b16b3b456922b82310add8c17bdf322b17bac82723dbe0ba1c120fee795097d399c6f3c4fa4bafebabfe7d08042d866d9476fe4d5b2cfb3739fd87dea7d1f31ba5f46f35f378d85f84d5d18230d3153da9aa0c2bb0679c64");
const auto nist_256_c = base16_chunk(NIST_512_256C);
constexpr auto nist_256_test_count = 6;

struct sha512_256_test
{
    const data_chunk& data;
    const data_array<256/8> expected;
};

const std_array<sha512_256_test, nist_256_test_count> sha512_256_tests
{
    sha512_256_test
    { nist_256_0, base16_array("c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a") },
    { nist_256_1, base16_array("c4ef36923c64e51e875720e550298a5ab8a3f2f875b1e1a4c9b95babf7344fef") },
    { nist_256_8, base16_array("d25265bf9cbc0dd2f108a2f5e8f69db7d15e5b8fe9100fe887dae20b6e054fe8") },
    { nist_256_a, base16_array("00ce3b592d4e1a65f780df351fa7b2c01b49df4ea913c3fab24297f5791b18e5") },
    { nist_256_b, base16_array("f4d4a7b83262eaab269417828e525e9a6dc9fcb672c8cffdab634795a180eaa1") },
    { nist_256_c, base16_array("05be6b585d2daed5b9bba5991df1c1405e1695b236e194463dc0368af83a2d8d") }
};

// sha512_224_tests
// ----------------------------------------------------------------------------
// FIPS 180-4 adds two algorithms: SHA-512/224 and SHA-512/256.
// The above vectors have not been updated for FIPS 180-4, so use these:
// csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Secure-Hashing

const auto nist_224_0 = base16_chunk("");
const auto nist_224_1 = base16_chunk("cf");
const auto nist_224_8 = base16_chunk("6963446913771410");
const auto nist_224_a = base16_chunk("9625ae618ea633fd7ae5b20ceafd6b1f3ab1a6aa20aded66810e78f38925e9c2fa783a32c40af3f9d7dda0c635b482254b1d85a281af7231109166cd133c8360e281e5e39bcdd7c601ac47928a8c78cdb3c4f71e97d4d0b1c0ee01dd3db62f04f44798bb3a76492ba15a91b7110cb5e01babe56589a36fae3a2f336a2d1d5778dbd23c03ca8db0f25ff0657ff4bca1252adc38c080a5b8f0255ce3be0bf862823d2ab704729b74e1e275aa305824a566895ed677a460113e2a7bf91f00d0b8ebc358f3035b27fcc1d3f14a1367cd2769df39a9d21c5ee361f1965cd6342cc17a1463d6");
const auto nist_224_b = base16_chunk("d0ba5d806099503abf1168ae6c34c0a1e124445d18835bbc4e2aca82071ed5ef52bfa6954e43f368ed63dc14f854129354f93efe8357a1a36d49f7596175a210577e04ac787c2d14e0a9b685a25cec2d0c3c32f52dada09e958ff00f5c289bed665e3f6de42a44661e49bfab713596979353e6e91f6ea1d24d647c4d001f08af07c71e7f9c36818731adbf2b6dc558fa71a822835f80ec6a1d3062bb5643317dc2216b8ba8892c9fa13b7eb09ef57a7e2ca1b06bf7cdc98c8d5b6b00657a5d8020d5ec380e0a8dd5f45dc3e00dae434a4ea85748ee3c8061264d5fc436add5e0a8496a2fd8a0eb52b47a5763c1d6fd875f24dec24db458106f6f06b1cfc5e2c4e3e6ac170e35903e68f903e2c256ee5ce57d0e821b1f9ac1f127276d3aa8ca5457147c99b6b0c2c099448d0519175ef26a1aaf3060648f9e32de8ca07f40d5ba8e3ca05ddaf8ca00cec2bd73cd00977075658974256b7cccbcfdfbf3a4734d1b10c4e10a81f7f0278fdb5dd5e6f8e0ff8fc563f4711cac7617ea3d0db32b78a263160748b4947b5d65f733d26de980c73ea2065b4c5f66c2c90f1a98b34fa0741198dac17ab7b5c9d67e091369bac0ef0d653b4fbe1cf1d85cd35939adc70bbca2b4221adb48e4946cd8a53fe253e8a08174c878d03b96e1589dc49aa87b01a09cd1a6fedf3051e5af6ecfffe09c40012438758089a49d0543d72163ac53cc4889562f138f5544e526a651fb6c7d0f3b7d190c0cf23f4e6ba7e8393cc237b3ddf0ad8501f2a004bc59e9f2da8dde9f75148053c711f5f03c0b38d4cbf00ffd875a3d707110f9db91d0a079454ca736d872d31456f0accd9ff82fbabb40c3f36d4e6eb80bf2490f8c1431afe3afc01d8c1e7b1564974d2bbdf535b2b2ba3bddb854a824769f76e9d7ac065c5dc1119cb8a0e11f970cc153be8ab28558655f038ff4537d5b1f6ab1972085485a8782fa84816cf99759ee8dc93f0efb574918ac1bb7d78b617b0baff7f9183a830bfc811948836d0d86be21069db1dc546e4c2184249d1631ba432b1dbe26fb805465779f7d9041a19918569e2b03f0fadde4abf1c40be672e4f96c31f71754f86aa7253da9fa3efa9ce375b9716dffee9dc9908a1d8ac2cd0215bb5c2c520a9356a8d31c53292cc19609c67ef855d0dbb6e11879b98374ea1b7e60c5e641e8fa1f52c9640385d39d9071911647242c6731168de3205cc270371ea396ac4bb5d5cd8b4e3c4176fa3791031ea9e743db3a154f35f3d87f75085edccbf407d838cb693dabcc96646b36a1a7b45e5e18a5fd6a745ace6b52555999a022097e503a85f94f293d89b7ec43c8459d5d360d5258386c429f613f290cef52eefd991c83ab88a90eb7a3d746060fc51fcff689a9f28821358c40acbbc869db78f8e0a2dbe41b33a2616a2c41267d0f83dc27f47374617a7dbd9203d1360e210821dc4b0ad8bcd52f64681fa44c1b0c11ab50b57885cc5f615bdeab34fde60de6a0147fd7307277fbe82516391ff0a21065f93680ced0b8288ead0cacc6f987599e10a70c9446014f14287ac64804baca31abde53f7756d1b7d868e00395078aa4359296fab3e5b7310f9b4146e5f3d8538ec15b8a7c3678251f199fafdf2c622b6766fc91e656daf05202aeb3a0a118aa147437986c38ca531769560bbe75b0720efdfe194c0204b1b254612540c20219541d05c3d7cc5cb469eeafb1a381da1a84de381b6595a8e79916f53636d50913c64252a74f6fb3db8f00093c3ecf63a7717e26f2c3704c248ec0c740f358b24bd37a8aad23a1444aef540f05d0bcd18b4d544749d62072dafbc873e026db8204142c2a6004ffa26503310d9919e898488107058b2e34917d78b4779e11dbfceef0edbe4a63d932bc734d91707ab14c61b4ed0e312c1b4cae7e0b4ed574b8876f0225c2e6b0dc99d3b800473663d5526941acbdd65042f8d084436610a01fa606b06ab4af7c682c2d39df7b2575934ec1bf9c90d55b5a1a7623e359fa246ffd389433200f370a8e4b8151c9f8109995fda75323c88daf4611c56196dc8237e197260581a071422491270da018d546cc8f6156f32a67e0f035f144a94249e60784de5845edab9d8390834989f2243956f9a61e6b758a6dad5520131dc5dc28b39425b20961567b2fec2ebc042e9dcfd9cece20093465c3d1e1ea4340c1b94e8a37b4993885f2698df691cb9b289298a97141f258d17a72028ea85bcee081e5f001d3745fd61ff72232550ebb7ab3225a73ba1be6f73906b39df2d3248ca67d99653ad9ebcc3f928131d0ebe19f7feb71689ee31ff041d069a2523fce309773caf4334068f2c1da2f77ade9a9f1495262a2590e8066f58d993e3ef84876e5772911553e53c4472c9176348e713abff5c2c380f494b5f49cd6b411a30fba00e6184f293a38cb40083ba01d50d3b63443f63e9f1be987af7c86c682b6a0948a4f3d2027ba84724cfb9297c0c74dfe56db91961c0aeb3686ab3dc80aa99770e220ec16c935c353be854adfb7684c9d982b194c7038165d2aa7704b020240e998f9c9b5963281da2523a8ca699a6c0e5890e1e44439e7660c0fa2c2114759692f384a6f07472c90115550ea6ff408bb48cbafd00076faeb9b3269cfb0ef3d7a056ae2b5a4da3ffff3a8b7d2330bcf3ec929c7922d75bd5868be29b659606996cc10271be76248844c7c61f44b380c036a49cdcd33bcab26e501572873516a39e3b68c245785c2c79c7ed3e320ff6ba39c9a26c3abc240e1a0ba96a8a728bbeddcdc86416dab2b2463fe82015cf84a89e09967380e1d2b131c485c996d6ceb2d17e0aa05b2490e452399f0d147894540c6c6037cc333a635c8191d7d2e84547235616be39df5d8846bcfa4f57948d842cfbe9014739c5ec434cb5de673059447b5dd406da928067c9d1e12d07aad701a6bd1718187bdb138d2cd9247d367273809c2dc066c56349847f3cee4c43da9321bbd3c66981e5a1e32ae5f23a83f99adb1a073304006df61ecef3db4de6fd0145fb06515fd4495fec4cc190c99e548234df4ca8ddcc063540c6ee3c331bab15bb87960224fb7112519c5646500fedf331f4e26719b096cf92701559256b49952b676d21e07ec385b9228a5cf85f2bb57d60b3b8df35858dbbd351794c5c404a3ca171f6bae6a97fcde54619e815758fbe2ba5e357e13c3564f788e5d078f8fc973f8cc8dbb98ac735ed73c749b9354a9d5ea22fab3f218f34e5a3e6d847d973e448a5e16b82ce269842f7ac42d3d2aec10091e600d49d65d4a48bc28c504c76cac5a38791c6dc649eedbc10fcecb483d319594e812a197deb3c26c1151bb7cff1bd7003750f1e49f0f5a83d9e8b43917ab2e4af53c8fba022b65e2d9b3083440238f39d40e4fb9c3662a57a5139e7a05fd11953a136ac9621191a4c4518199ea53f149c1acedb27173c9a0e3d7d08772981e08191fd95278f6d42683c5adfa481d8bb4a2a5426b03c8c6e4289df0edf81c721804ba41d1b15bbbdc7a87e3f203f0ed0ed99fe45004d5a0b5e5ee761a00fadc499f8b3ab395a0a75b1b00ca0d886e63bce8e549edff1ac58aae31e69827a3ab214c0b2a94a076251707c8d6a96ff6ae43532df9a15d08c3d6d410b8e4d6b76d139ca2a7e16c3cb394b3589042052a1b469ad26a1699301a2f19f3739c8896a0a4f3fa39265374e15890386d83e269391b426b11ca4e2136f7c2628d0bc7d1d46a046a34dff0af2cd730d0e4dba2349645cc509718e64cb8c57fd68bdf1ee976b7208b417ace5c04a517ca8cb5bf2ca16aab4b50aefc230e2ca4e7f662f85e1620ead5d583370be726b77ddbae83b1e8de6183d4d8fa44b571c3ef3353eea0214bc5c27785d52f62e082733832aa54eb3581c2aa436b022d497f74e90e5c40268c43d98dff234706771b4348ce9d9616f48e50376ab91c04281a117e1edbbea456d793af5babd3303ef45683eec7f5fa8fd9e502bb7ed2a872363d78f1f78c195003895237c9647ecc8025601fd3e5148c06d9a2b226d6a8dc566150241a38f3fc5a12fcf0266b4084414863ee2be3e36d97a67ddb4b8863aafd259a21be45d2b04dd926312d68241ada3805b64a82e5a90ee42ab3477897828ce2cd777e1324105134645758eba7d49d6cdc24ba4299c2cf1b0fc6c51782e798214091b4516690f6cd1dff33564a662d6f4d95f5938e4f7aa3b3922ef5d44eb179ba0d0b6118b6c10bd97537386a33ecb7d0a6870621a37426ac81ff83fa1c4b549045edc2c8f622692d75ff22a5c25dcf1bc2d90b02635e1c5122b15272f4c83a59d8d616e5d3ad7d606dd5757b96131d656776228f039add57f0dee1cd5cdaa37d425eae0dd3c4a138b964d16a239f3b7420e8ed5618bd121788f2a267b8d52870fed2288f8afa8d0d0527a6efff44a19e7babbbc5f7273326377714d09d5a11eb7aeae7094dd18963cd88667b8db5d86ad4391e7d338bc8ea98e6d9a68edc283353039a09a0cc3ec37f21a09b5365585fc70ba5da623d3bfb39cc4147e1ddb3eef3b691ef385d05a2966de5ddf4d599f3c0adb26be7ce04de8691ec434ad15d84f97e6f4859068687afd796a1c67925ad5d99f4b058a0dbeafbc24b073e497d8bc0b592a3a74b39f937f943855cd284130a5abd36297809c725f7de2210c8ac69e616ac6f97bd886dab4d6d073c842d9b336aac6bce9616e9818d262276b152b5c5fc0d2a9eb00a6b864e8395c9e08acc754422cfdc9d9bd89b0cb366e49618d60ce0455340d52859656717bfa97a341d5c6");
const auto nist_224_c = base16_chunk(NIST_512_224C);
constexpr auto nist_224_test_count = 6;

struct sha512_224_test
{
    const data_chunk& data;
    const data_array<224/8> expected;
};

const std_array<sha512_224_test, nist_224_test_count> sha512_224_tests
{
    sha512_224_test
    { nist_224_0, base16_array("6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4") },
    { nist_224_1, base16_array("4199239e87d47b6feda016802bf367fb6e8b5655eff6225cb2668f4a") },
    { nist_224_8, base16_array("21f6c373637e6a5e89d6e88811110c5c3fa12e497144912914c546e1") },
    { nist_224_a, base16_array("72640a79fbb1cfb26e09b4b35385389ed633a55e092906d01a7186e1") },
    { nist_224_b, base16_array("9ac5ca06d0d578cb270383692ea829f9b41b730471d65a0bcddd71ec") },
    { nist_224_c, base16_array("dbabf11d16c07e6033e6a4b23be8c6a9dd9a54bd66e67246206bff51") }
};

// hmac
// ============================================================================

// test vectors
// datatracker.ietf.org/doc/html/rfc2202 (sha160)
// datatracker.ietf.org/doc/html/rfc4231 (sha256/512)

const auto hmac_1k = base16_chunk("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
const auto hmac_1d = to_chunk("Hi There");
const auto hmac_2k = to_chunk("Jefe");
const auto hmac_2d = to_chunk("what do ya want for nothing?");
const auto hmac_3k = base16_chunk("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
const auto hmac_3d = base16_chunk("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd");
const auto hmac_4k = base16_chunk("0102030405060708090a0b0c0d0e0f10111213141516171819");
const auto hmac_4d = base16_chunk("cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd");
const auto hmac_5k = base16_chunk("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c");
const auto hmac_5d = to_chunk("Test With Truncation"); // not truncated here.
const auto hmac_6k = base16_chunk("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
const auto hmac_6d = to_chunk("Test Using Larger Than Block-Size Key - Hash Key First");
const auto hmac_7k = base16_chunk("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
const auto hmac_7d = to_chunk("This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.");
constexpr auto hmac_test_count = 7;

// hmac_sha160_tests
// ----------------------------------------------------------------------------

struct hmac_sha160_test
{
    const data_chunk& key;
    const data_chunk& data;
    const short_hash expected;
};

// This is the subset of rfc2202 vectors in common with rfc4231.
const std_array<hmac_sha160_test, 2> hmac_sha160_tests
{
    hmac_sha160_test
    { hmac_1k, hmac_1d, base16_array("b617318655057264e28bc0b6fb378c8ef146be00") },
    { hmac_2k, hmac_2d, base16_array("effcdf6ae5eb2fa2d27416d5f184df9c259a7c79") }
};

// hmac_sha256_tests
// ----------------------------------------------------------------------------

struct hmac_sha256_test
{
    const data_chunk& key;
    const data_chunk& data;
    const hash_digest expected;
};

const std_array<hmac_sha256_test, hmac_test_count> hmac_sha256_tests
{
    hmac_sha256_test
    { hmac_1k, hmac_1d, base16_array("b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7") },
    { hmac_2k, hmac_2d, base16_array("5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843") },
    { hmac_3k, hmac_3d, base16_array("773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe") },
    { hmac_4k, hmac_4d, base16_array("82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b") },
    { hmac_5k, hmac_5d, base16_array("a3b6167473100ee06e0c796c2955552bfa6f7c0a6a8aef8b93f860aab0cd20c5") },
    { hmac_6k, hmac_6d, base16_array("60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54") },
    { hmac_7k, hmac_7d, base16_array("9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2") }
};

// hmac_sha512_tests
// ----------------------------------------------------------------------------

struct hmac_sha512_test
{
    const data_chunk& key;
    const data_chunk& data;
    const long_hash expected;
};

const std_array<hmac_sha512_test, hmac_test_count> hmac_sha512_tests
{
    hmac_sha512_test
    { hmac_1k, hmac_1d, base16_array("87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854") },
    { hmac_2k, hmac_2d, base16_array("164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737") },
    { hmac_3k, hmac_3d, base16_array("fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb") },
    { hmac_4k, hmac_4d, base16_array("b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd") },
    { hmac_5k, hmac_5d, base16_array("415fad6271580a531d4179bc891d87a650188707922a4fbb36663a1eb16da008711c5b50ddd0fc235084eb9d3364a1454fb2ef67cd1d29fe6773068ea266e96b") },
    { hmac_6k, hmac_6d, base16_array("80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598") },
    { hmac_7k, hmac_7d, base16_array("e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58") }

};

// pbkd
// ============================================================================

// pbkd_sha160_tests
// ----------------------------------------------------------------------------
// www.ietf.org/rfc/rfc6070.txt

struct pbkd_sha160_test
{
    const std::string passphrase;
    const std::string salt;
    const size_t count;
    const short_hash expected;
};

const std_array<pbkd_sha160_test, 3> pbkd_sha160_tests
{
    pbkd_sha160_test
    {
        "password",
        "salt",
        2,
        base16_array("ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957")
    },
    {
        "password",
        "salt",
        4096,
        base16_array("4b007901b765489abead49d926f721d065a429c1")
    },
    {
        "password",
        "salt",
        16777216,
        base16_array("eefe3d61cd4da4e4e9945b3d6ba2158c2634e984")
    }
};

// pbkd_sha256_tests
// ----------------------------------------------------------------------------
// www.rfc-editor.org/rfc/rfc7914.txt

struct pbkd_sha256_test
{
    const std::string passphrase;
    const std::string salt;
    const size_t count;
    const long_hash expected;
};

const std_array<pbkd_sha256_test, 2> pbkd_sha256_tests
{
    pbkd_sha256_test
    {
        "passwd",
        "salt",
        1,
        base16_array("55ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783")
    },
    {
        "Password",
        "NaCl",
        80000,
        base16_array("4ddcd8f60b98be21830cee5ef22701f9641a4418d04c0414aeff08876b34ab56a1d425a1225833549adb841b51c9b3176a272bdebba1d078478f62b397f33c8d")
    }
};

// pbkd_sha512_tests
// ----------------------------------------------------------------------------
// github.com/Anti-weakpasswords/PBKDF2-Test-Vectors/releases

struct pbkd_sha512_test
{
    const std::string passphrase;
    const std::string salt;
    const size_t count;
    const long_hash expected;
};

const std_array<pbkd_sha512_test, 5> pbkd_sha512_tests
{
    pbkd_sha512_test
    {
        "password",
        "salt",
        1,
        base16_array("867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce")
    },
    {
        "password",
        "salt",
        2,
        base16_array("e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e")
    },
    {
        "password",
        "salt",
        4096,
        base16_array("d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f30602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5")
    },
    {
        "passwordPASSWORDpassword",
        "saltSALTsaltSALTsaltSALTsaltSALTsalt",
        4096,
        base16_array("8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8")
    },
    {
        "password",
        "NaCL",
        1,
        base16_array("73decfa58aa2e84f94771a75736bb88bd3c7b38270cfb50cb390ed78b305656af8148e52452b2216b2b8098b761fc6336060a09f76415e9f71ea47f9e9064306")
    }
};

// scrypt_tests
// ============================================================================
// Also rfc7914 tests inline.

struct scrypt_hash_test
{
    const data_array<80> data;
    const hash_digest expected;
};

const std_array<scrypt_hash_test, 5> scrypt_hash_tests
{
    scrypt_hash_test
    {
        base16_array("020000004c1271c211717198227392b029a64a7971931d351b387bb80db027f270411e398a07046f7d4a08dd815412a8712f874a7ebf0507e3878bd24e20a3b73fd750a667d2f451eac7471b00de6659"),
        base16_array("065898d7ab2daa8235cdda9511d248f3010b5e11f682f80741ef2b0000000000")
    },
    {
        base16_array("0200000011503ee6a855e900c00cfdd98f5f55fffeaee9b6bf55bea9b852d9de2ce35828e204eef76acfd36949ae56d1fbe81c1ac9c0209e6331ad56414f9072506a77f8c6faf551eac7471b00389d01"),
        base16_array("94fc881c9ff1da50d235ed28f2bbcfddfeb7084e63ebd5bd110d3a0000000000")
    },
    {
        base16_array("02000000a72c8a177f523946f42f22c3e86b8023221b4105e8007e59e81f6beb013e29aaf635295cb9ac966213fb56e046dc71df5b3f7f67ceaeab24038e743f883aff1aaafaf551eac7471b0166249b"),
        base16_array("81caa81451ddf8659cf2afd8599d2d6c8a724432e188f295f8400b0000000000")
    },
    {
        base16_array("010000007824bc3a8a1b4628485eee3024abd8626721f7f870f8ad4d2f33a27155167f6a4009d1285049603888fe85a84b6c803a53305a8d497965a5e896e1a00568359589faf551eac7471b0065434e"),
        base16_array("fe05e1971818866adc7e8e6e2fd7e8d8991e032349cd91580007300000000000")
    },
    {
        base16_array("0200000050bfd4e4a307a8cb6ef4aef69abc5c0f2d579648bd80d7733e1ccc3fbc90ed664a7f74006cb11bde87785f229ecd366c2d4e44432832580e0608c579e4cb76f383f7f551eac7471b00c36982"),
        base16_array("8cec00384d72c7e74f5b340d73af02fa47cb0c13c7afa426b4f0180000000000")
    }
};

#endif
